diff --git a/asm/overlay_29_02313CE4.s b/asm/overlay_29_02313CE4.s index 1fb2870c..dcf84b70 100644 --- a/asm/overlay_29_02313CE4.s +++ b/asm/overlay_29_02313CE4.s @@ -4,165 +4,7 @@ .text - arm_func_start ApplyOffensiveStatMultiplier -ApplyOffensiveStatMultiplier: ; 0x02313D40 -#ifdef JAPAN -#define APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -0x2C0 -#else -#define APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET 0 -#endif - stmdb sp!, {r0, r1, r2, r3} - stmdb sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - mov r8, r1 - mov sb, r0 - mov r7, r3 - bl AllocateTemp1024ByteBufferFromPool - mov r4, r0 - mov r0, r8 - bl EntityIsValid__023118B4 - cmp r0, #0 - beq _02313F3C - ldr r0, [sp, #0x28] - cmp r0, #0 - beq _02313D94 - ldr r1, _02313F48 ; =0x00000DCB - mov r0, r4 - bl CopyStringFromId - mov r1, r4 - mov r0, #1 - bl SetMessageLogPreprocessorArgsString - b _02313DAC -_02313D94: - ldr r1, _02313F4C ; =0x00000DCA - mov r0, r4 - bl CopyStringFromId - mov r1, r4 - mov r0, #1 - bl SetMessageLogPreprocessorArgsString -_02313DAC: - cmp r7, #0x100 - bge _02313DCC - ldrb r2, [sp, #0x30] - mov r0, sb - mov r1, r8 - bl IsProtectedFromStatDrops - cmp r0, #0 - bne _02313F3C -_02313DCC: - mov r0, r8 - mov r1, #0x12 - bl ItemIsActive__02311BF8 - cmp r0, #0 - beq _02313E0C - cmp r7, #0x100 - bge _02313E0C - mov r0, #0 - mov r1, r8 - mov r2, r0 - bl SubstitutePlaceholderStringTags - ldr r2, _02313F50 ; =0x00000DB2 - mov r0, sb - mov r1, r8 - bl LogMessageByIdWithPopupCheckUserTarget - b _02313F3C -_02313E0C: - mov r0, sb - mov r1, r8 - mov r2, #9 -#ifndef JAPAN - mov r3, #1 -#endif - bl DefenderAbilityIsActive__02311B94 - cmp r0, #0 - beq _02313E6C - ldr r0, [sp, #0x28] - cmp r0, #0 - bne _02313E6C - cmp r7, #0x100 - bge _02313E6C - ldrb r0, [sp, #0x30] - cmp r0, #0 - beq _02313F3C - mov r0, #0 - mov r1, r8 - mov r2, r0 - bl SubstitutePlaceholderStringTags - ldr r2, _02313F54 ; =0x00000D9E - mov r0, sb - mov r1, r8 - bl LogMessageByIdWithPopupCheckUserTarget - b _02313F3C -_02313E6C: - mov r0, #0 - mov r1, r8 - mov r2, r0 - ldr r5, [r8, #0xb4] - bl SubstitutePlaceholderStringTags - ldr r6, [sp, #0x28] - cmp r7, #0x100 - add r0, r5, r6, lsl #2 - ldr r4, [r0, #0x34] - add r1, sp, #0x28 - mov r0, r8 - bge _02313EA8 - ldr r1, [r1] - bl ov29_022E5068 - b _02313EB0 -_02313EA8: - ldr r1, [r1] - bl ov29_022E4FC0 -_02313EB0: - add r0, r5, r6, lsl #2 - ldr r0, [r0, #0x34] - mov r1, r7 - bl MultiplyByFixedPoint - add r1, r5, r6, lsl #2 - str r0, [r1, #0x34] - cmp r0, #2 - movlt r0, #2 - strlt r0, [r1, #0x34] - add r2, r5, r6, lsl #2 - ldr r1, [r2, #0x34] - ldr r0, _02313F58 ; =0x000063FD - cmp r1, r0 - strgt r0, [r2, #0x34] - add r0, r5, r6, lsl #2 - ldr r0, [r0, #0x34] - cmp r4, r0 - ble _02313F0C - ldr r2, _02313F5C ; =0x00000DD1 - mov r0, sb - mov r1, r8 - bl LogMessageByIdWithPopupCheckUserTarget - b _02313F34 -_02313F0C: - bge _02313F24 - mov r0, sb - mov r1, r8 - mov r2, #0xdd0 + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET - bl LogMessageByIdWithPopupCheckUserTarget - b _02313F34 -_02313F24: - ldr r2, _02313F60 ; =0x00000DD3 - mov r0, sb - mov r1, r8 - bl LogMessageByIdWithPopupCheckUserTarget -_02313F34: - mov r0, r8 - bl UpdateStatusIconFlags -_02313F3C: - ldmia sp!, {r3, r4, r5, r6, r7, r8, sb, lr} - add sp, sp, #0x10 - bx lr - .align 2, 0 -_02313F48: .word 0x00000DCB + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -_02313F4C: .word 0x00000DCA + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -_02313F50: .word 0x00000DB2 + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -_02313F54: .word 0x00000D9E + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -_02313F58: .word 0x000063FD -_02313F5C: .word 0x00000DD1 + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET -_02313F60: .word 0x00000DD3 + APPLY_OFFENSIVE_STAT_MULTIPLIER_OFFSET - arm_func_end ApplyOffensiveStatMultiplier + arm_func_start ApplyDefensiveStatMultiplier ApplyDefensiveStatMultiplier: ; 0x02313F64 diff --git a/include/math.h b/include/math.h index ee4c3881..d6b9161e 100644 --- a/include/math.h +++ b/include/math.h @@ -7,5 +7,11 @@ #define F248LessThanFloat(x, y) (x < (int)(y * 0x100)) #define F248LessThanInt(x, y) (x < 0x100 * y) +#define FloatToF248(x) (x * 0x100) +#define FloatLessThanF248(x, y) ((int)(x * 0x100) < y) +#define F248LessThan(x, y) (x < y) +#define F248GreaterThan(x, y) (x > y) +#define F248Equal(x, y) (x == y) +#define F248EqualsInt(x, y) (x == 0x100 * y) -#endif //PMDSKY_MATH_H \ No newline at end of file +#endif // PMDSKY_MATH_H diff --git a/include/overlay_29_02313814.h b/include/overlay_29_02313814.h index 151b381a..391f286d 100644 --- a/include/overlay_29_02313814.h +++ b/include/overlay_29_02313814.h @@ -1,6 +1,7 @@ #ifndef PMDSKY_OVERLAY_29_02313814_H #define PMDSKY_OVERLAY_29_02313814_H +#include "util.h" #include "dungeon_mode.h" enum flash_fire_status { @@ -27,5 +28,6 @@ void BoostDefensiveStat(struct entity *user, struct entity *target, struct StatI // This checks that the defender is valid and Flash Fire is active, and that Normalize isn't active on the attacker. enum flash_fire_status GetFlashFireStatus(struct entity *attacker, struct entity *defender); void ActivateFlashFire(struct entity *pokemon, struct entity *target); +void ApplyOffensiveStatMultiplier(struct entity *user, struct entity *target, struct StatIndex stat, fx32_8 multiplier, bool8 displayMessage); #endif //PMDSKY_OVERLAY_29_02313814_H diff --git a/src/overlay_29_02313814.c b/src/overlay_29_02313814.c index 8214e794..dc901dbd 100644 --- a/src/overlay_29_02313814.c +++ b/src/overlay_29_02313814.c @@ -3,6 +3,7 @@ #include "overlay_29_023118B4.h" #include "overlay_29_02313814.h" #include "overlay_29_02311BF8.h" +#include "math.h" extern u8* AllocateTemp1024ByteBufferFromPool(void); extern void CopyStringFromId(u8* buf, u32 string_id); @@ -13,9 +14,12 @@ extern void PlayOffensiveStatUpEffect(struct entity *user, struct StatIndex); extern void PlayDefensiveStatDownEffect(struct entity *user, struct StatIndex); extern void PlayDefensiveStatUpEffect(struct entity *user, struct StatIndex); extern void PlayOffensiveStatDownEffect(struct entity *user, struct StatIndex); +extern void ov29_022E5068(struct entity *user, struct StatIndex); +extern void ov29_022E4FC0(struct entity *user, struct StatIndex); extern void LogMessageByIdWithPopupCheckUserTarget(struct entity *user, struct entity *target, u32 message_id); extern void UpdateStatusIconFlags(struct entity *); extern void ov29_022E4338(struct entity *); +extern fx32_8 MultiplyByFixedPoint(fx32_8 a, fx32_8 b); #ifdef JAPAN #define JPN_MSG_OFFSET -0x2C0 @@ -294,3 +298,77 @@ void ActivateFlashFire(struct entity *pokemon, struct entity *target) UpdateStatusIconFlags(target); } } + +void ApplyOffensiveStatMultiplier(struct entity *user, struct entity *target, struct StatIndex stat, fx32_8 multiplier, bool8 displayMessage) +{ + struct monster *entityInfo; + fx32_8 oldMulti; + u8 *buffer1 = AllocateTemp1024ByteBufferFromPool(); + + if (!EntityIsValid__023118B4(target)) + return; + + if (stat.id != STAT_INDEX_PHYSICAL) { + CopyStringFromId(buffer1, 0xdcb + JPN_MSG_OFFSET); + SetMessageLogPreprocessorArgsString(1, buffer1); + } + else { + CopyStringFromId(buffer1, 0xdca + JPN_MSG_OFFSET); + SetMessageLogPreprocessorArgsString(1, buffer1); + } + + if (F248LessThanInt(multiplier, 1) && IsProtectedFromStatDrops(user,target,displayMessage)) + return; + + if (ItemIsActive__02311BF8(target,ITEM_TWIST_BAND) && F248LessThanInt(multiplier, 1)) { + SubstitutePlaceholderStringTags(0,target,0); + LogMessageByIdWithPopupCheckUserTarget(user,target,0xdb2 + JPN_MSG_OFFSET); + return; + } + + #ifdef JAPAN + if (DefenderAbilityIsActive__02311B94(user, target, ABILITY_HYPER_CUTTER) + #else + if (DefenderAbilityIsActive__02311B94(user, target, ABILITY_HYPER_CUTTER, TRUE) + #endif // JAPAN + && stat.id == STAT_INDEX_PHYSICAL + && F248LessThanInt(multiplier, 1)) + { + if (displayMessage) { + SubstitutePlaceholderStringTags(0,target,0); + LogMessageByIdWithPopupCheckUserTarget(user,target,0xd9e + JPN_MSG_OFFSET); + } + return; + } + + entityInfo = GetEntInfo(target); + SubstitutePlaceholderStringTags(0,target,0); + oldMulti = entityInfo->stat_modifiers.offensive_multipliers[stat.id]; + + if (F248LessThanInt(multiplier, 1)) { + ov29_022E5068(target,stat); + } + else { + ov29_022E4FC0(target,stat); + } + + entityInfo->stat_modifiers.offensive_multipliers[stat.id] = MultiplyByFixedPoint(entityInfo->stat_modifiers.offensive_multipliers[stat.id],multiplier); + + if (F248LessThanFloat(entityInfo->stat_modifiers.offensive_multipliers[stat.id], 0.01)) { + entityInfo->stat_modifiers.offensive_multipliers[stat.id] = FloatToF248(0.01); + } + if (FloatLessThanF248(99.99, entityInfo->stat_modifiers.offensive_multipliers[stat.id])) { + entityInfo->stat_modifiers.offensive_multipliers[stat.id] = FloatToF248(99.99); + } + + if (F248GreaterThan(oldMulti, entityInfo->stat_modifiers.offensive_multipliers[stat.id])) { + LogMessageByIdWithPopupCheckUserTarget(user,target,0xdd1 + JPN_MSG_OFFSET); + } + else if (F248LessThan(oldMulti, entityInfo->stat_modifiers.offensive_multipliers[stat.id])) { + LogMessageByIdWithPopupCheckUserTarget(user,target,0xdd0 + JPN_MSG_OFFSET); + } + else { + LogMessageByIdWithPopupCheckUserTarget(user,target,0xdd3 + JPN_MSG_OFFSET); + } + UpdateStatusIconFlags(target); +}