F2: new change to the damage calculation - hopefully a fix

Discussion in 'Fallout General Modding' started by Glovz, Jun 9, 2010.

  1. Magnus

    Magnus Water Chip? Been There, Done That
    Modder

    953
    Dec 6, 2007
    How do you go about debugging this thing? I've tried in ollydbg for a while, but I can't get back to desktop when the game hits a breakpoint, and just looking through the code when it's not running isn't enough.
     
  2. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    Hi Haen,

    I have no problem with the offtopic discussion carrying on in this thread, but to help others follow it would be useful if a moderator or admin could move the relevant posts to another thread with you or me as the owner.

    I believe I understand clearly enough what's going on in the code snippet you provided, if you post more of the code hopefully I can help with some of it.

    @Magnus
    Hopefully Haen can provide you with some tips; like I said earlier, I've never been really good at that myself. I used to inject changes where space allowed and test them through the game; very time consuming and very limiting.

    Thank goodness Timeslip came along and allowed for a better method for adding/replacing/bypassing code in the exe.
     
  3. Nevill

    Nevill First time out of the vault

    85
    Mar 14, 2007
    Hi.

    I would like to add that so far I very much approve of what you've done with damage formula. It would be fun to play F2 with these changes when RP 2.1 finally comes out. That's why I'll continue trying to convince you - because I'd like to try your fix.

    If you fix it like you are currently suggesting, there will be very little randomisation in unarmed attacks damage. Basically, it will differ by 1 pt only, except for the criticals. It will make combat very predictable and bland.

    From game balance viewpoint, I'd say that 2 additional pts of guaranteed damage from the perk is fine, but potential 9 extra pts (5 from STR, 4 from trait) is, in my opinion, an overkill.
     
  4. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    Below are resulting ranges from using the following formulas with HtH attacks (no weapon). If the player was using a melee weapon then the result sets would scale based on the weapons range but unarmed attack bonus would NOT be applied.

    Code:
    Hand 1-2
    
    player strength 4,5,6,7,8,9,10
    
    original
    raw_damage = random(min_damage_of_weapon, max_damage_of_weapon + bonus_melee_damage) 
    bonus_melee_damage = max(player_strength - 5, 1) + heavy_handed_bonus + (2 * rank_of_bonus_hth_damage_perk)
    raw_damage = random(1 + unarmed_attack_bonus, 2 + bonus_melee_damage + unarmed_attack_bonus). 
    
    Glovz fix
    raw_damage = random(min_damage_of_weapon, max_damage_of_weapon) + bonus_melee_damage 
    bonus_melee_damage = max(player_strength - 5, 1 + (2 * rank_of_bonus_hth_damage_perk)) + heavy_handed_bonus 
    raw_damage = random(1 + unarmed_attack_bonus, 2 + unarmed_attack_bonus) + bonus_melee_damage 
    
    Nevill fix
    raw_damage = random(min_damage_of_weapon, max_damage_of_weapon + bonus_melee_damage) + (2 * rank_of_bonus_hth_damage_perk) 
    bonus_melee_damage = max(player_strength - 5, 1) + heavy_handed_bonus 
    raw_damage = random(1 + unarmed_attack_bonus, 2 + bonus_melee_damage + unarmed_attack_bonus) + (2 * rank_of_bonus_hth_damage_perk).  
    
    
    Original
    Hand, no heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      1-3
    5      1-3
    6      1-3
    7      1-4
    8      1-5
    9      1-6
    10     1-7
    
    
    Hand, heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      1-7
    5      1-7
    6      1-7
    7      1-8
    8      1-9
    9      1-10
    10     1-11
    
    
    Hand, heavy handed, one level bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      1-9
    5      1-9
    6      1-9
    7      1-10
    8      1-11
    9      1-12
    10     1-13
    
    
    Hand, heavy handed, one level bonus HtH, unarmed attack bonus (2?)
    
    ST     Range
    4      3-11
    5      3-11
    6      3-11
    7      3-12
    8      3-13
    9      3-14
    10     3-15
    
    
    Glovz' Fix
    Hand, no heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      2-3
    5      2-3
    6      2-3
    7      3-4
    8      4-5
    9      5-6
    10     6-7
    
    
    Hand, heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      6-7
    5      6-7
    6      6-7
    7      7-8
    8      8-9
    9      9-10
    10     11-12
    
    
    Hand, heavy handed, one level bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      7-7
    5      7-7
    6      7-7
    7      7-8
    8      8-9
    9      9-10
    10     11-12
    
    
    Hand, heavy handed, one level bonus HtH, unarmed attack bonus (2?)
    
    ST     Range
    4      9-9
    5      9-9
    6      9-9
    7      9-10
    8      10-11
    9      11-12
    10     13-14
    
    
    Nevill's Fix
    Hand, no heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      1-3
    5      1-3
    6      1-3
    7      1-4
    8      1-5
    9      1-6
    10     1-7
    
    
    Hand, heavy handed, no bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      1-7
    5      1-7
    6      1-7
    7      1-8
    8      1-9
    9      1-10
    10     1-11
    
    
    Hand, heavy handed, one level bonus HtH, no unarmed attack bonus
    
    ST     Range
    4      3-9
    5      3-9
    6      3-9
    7      3-10
    8      3-11
    9      3-12
    10     3-13
    
    
    Hand, heavy handed, one level bonus HtH, unarmed attack bonus (2?)
    
    ST     Range
    4      5-11
    5      5-11
    6      5-11
    7      5-12
    8      5-13
    9      5-14
    10     5-15
    Also remember once through the formulas above, the raw damage value picked randomly from the range is then put through the full damage calculation.
    Code:
            Original Formula                               Fixed Formula                                     
            N     LA     MA     CA     PA     APA          N     LA     MA     CA     PA     APA   
    ADT     0     2      4      5      12     15           0     2      4      5      12     15
    ADR     0     25     30     40     40     55           0     25     30     40     40     55
    --------------------------------------------------------------------------------------------
    1       1     0      0      0      0      0            2     0      0      0      0      0
    2       2     0      0      0      0      0            3     1      0      0      0      0
    3       3     1      0      0      0      0            4     2      0      0      0      0
    4       4     2      0      0      0      0            5     3      0      0      0      0
    5       5     3      1      0      0      0            6     4      1      0      0      0
    6       6     3      1      1      0      0            7     5      2      0      0      0
    7       7     4      2      1      0      0            8     6      3      1      0      0
    8       8     5      3      2      0      0            9     7      4      2      0      0
    9       9     5      4      2      0      0            10    8      5      3      0      0
    10      10    6      4      3      0      0            11    9      6      4      0      0
    11      11    7      5      4      0      0            12    10     7      5      0      0
    12      12    8      6      4      0      0            13    11     8      6      0      0
    13      13    8      6      5      1      0            14    12     9      7      0      0
    14      14    9      7      5      1      0            15    13     10     8      0      0
    15      15    10     8      6      2      0            16    14     11     9      0      0
    -------------------------------------------------------------------------------------------- 
     
  5. Haenlomal

    Haenlomal It Wandered In From the Wastes

    178
    Sep 25, 2003
    As requested, here's the assembly code to the function that returns the raw damage dealt in an attack (DamageFunctionSub1 in sfall), courtesy of OllyDbg. For your reference, I've also included the switch tables used in the case statements found in the function.

    The comments in about the switch tables and their associated conditional branching belong to OllyDbg. The rest of the comments are mine, from what I've been able to glean. Note that I'm uncertain of a lot of the things in there, so please take my comments with a grain of salt...or two! :) Those marked with "(?)" denotes high levels of uncertainty, more than the usual levels with which I am operating.

    What we really need is someone like crazycc or Timeslip to do this sort of stuff...

    Code:
    004783F8   . 7C844700       DD FALLOUT2.0047847C                     ;  Switch table used at 00478475
    004783FC   . 7C844700       DD FALLOUT2.0047847C
    00478400   . 83844700       DD FALLOUT2.00478483
    00478404   . 83844700       DD FALLOUT2.00478483
    00478408   . 8A844700       DD FALLOUT2.0047848A
    0047840C   . 8A844700       DD FALLOUT2.0047848A
    00478410   . 7C844700       DD FALLOUT2.0047847C
    00478414   . 83844700       DD FALLOUT2.00478483
    00478418   . C1844700       DD FALLOUT2.004784C1                     ;  Switch table used at 004784B9
    0047841C   . CB844700       DD FALLOUT2.004784CB
    00478420   . D5844700       DD FALLOUT2.004784D5
    00478424   . C1844700       DD FALLOUT2.004784C1
    00478428   . D5844700       DD FALLOUT2.004784D5
    0047842C   . E9844700       DD FALLOUT2.004784E9
    00478430   . CB844700       DD FALLOUT2.004784CB
    00478434   . D5844700       DD FALLOUT2.004784D5
    00478438   . DF844700       DD FALLOUT2.004784DF
    0047843C   . D5844700       DD FALLOUT2.004784D5
    00478440   . DF844700       DD FALLOUT2.004784DF
    00478444   . F0844700       DD FALLOUT2.004784F0
    00478448  /$ 53             PUSH EBX
    00478449  |. 51             PUSH ECX
    0047844A  |. 56             PUSH ESI
    0047844B  |. 57             PUSH EDI
    0047844C  |. 55             PUSH EBP
    0047844D  |. 83EC 10        SUB ESP,10
    00478450  |. 89C1           MOV ECX,EAX  ; pointer to critter
    00478452  |. 89D6           MOV ESI,EDX  ; hit_mode (see define.h hit_modes > 7 are apparently special unarmed attacks)
    00478454  |. 31D2           XOR EDX,EDX
    00478456  |. 31DB           XOR EBX,EBX
    00478458  |. 31ED           XOR EBP,EBP
    0047845A  |. 891424         MOV DWORD PTR SS:[ESP],EDX   ; set damage max = 0
    0047845D  |. 895424 04      MOV DWORD PTR SS:[ESP+4],EDX ; set damage min = 0
    00478461  |. 85C0           TEST EAX,EAX           ; sanity check for null critter pointer
    00478463  |. 0F84 FC000000  JE FALLOUT2.00478565   ; if null pointer exit function with value of 0
    00478469  |. 74 21          JE SHORT FALLOUT2.0047848C ; ??? -- This is unreacheable code
    0047846B  |. 83FE 07        CMP ESI,7 ; is hit_mode a special unarmed attack?
    0047846E  |. 77 1A          JA SHORT FALLOUT2.0047848A ; process unarmed attack if yes
    00478470  |. 89F7           MOV EDI,ESI
    00478472  |. C1E7 02        SHL EDI,2
    00478475  |. 2E:FFA7 F88347>JMP DWORD PTR CS:[EDI+4783F8] ; Otherwise, detect from which slot attack was made and get item pointer to it
    0047847C  |> E8 3B97FFFF    CALL FALLOUT2.00471BBC   ; weapon in left slot, get pointer to it
    00478481  |. EB 05          JMP SHORT FALLOUT2.00478488
    00478483  |> E8 E896FFFF    CALL FALLOUT2.00471B70   ; weapon in right slot, get pointer to it
    00478488  |> 89C2           MOV EDX,EAX
    0047848A  |> 89D0           MOV EAX,EDX  ; normal punch, kick, or special unarmed attack processing starts here
    0047848C  |> 89C7           MOV EDI,EAX
    0047848E  |. 85C0           TEST EAX,EAX        ; is left/right slot empty?
    00478490  |. 75 65          JNZ SHORT FALLOUT2.004784F7 ; skip ahead if yes
    00478492  |. BA 01000000    MOV EDX,1                        ; otherwise, no weapons used, so set min_unarmed_damage to 1
    00478497  |. 89C8           MOV EAX,ECX
    00478499  |. 895424 04      MOV DWORD PTR SS:[ESP+4],EDX     ; store min_unarmed_damage
    0047849D  |. BA 0B000000    MOV EDX,0B
    004784A2  |. E8 A16A0300    CALL FALLOUT2.004AEF48  ; Retrieve PC.Melee Damage Bonus
    004784A7  |. 83C0 02        ADD EAX,2               ; max_unarmed_damage = bonus_melee_damage + 2
    004784AA  |. 83EE 08        SUB ESI,8      ;  Switch (cases 8..13), also if hit_mode == 4, 5 (punch, kick), this will go back to 0047848A, but now with nonzero EDX value
    004784AD  |. 890424         MOV DWORD PTR SS:[ESP],EAX  ; store max_unarmed_damage
    004784B0  |. 83FE 0B        CMP ESI,0B
    004784B3  |. 0F87 9A000000  JA FALLOUT2.00478553
    004784B9  |. 2E:FF24B5 1884>JMP DWORD PTR CS:[ESI*4+478418] ; processing special unarmed attack bonus
    004784C1  |> BB 03000000    MOV EBX,3                                ;  Cases 8,B of switch 004784AA
    004784C6  |. E9 88000000    JMP FALLOUT2.00478553
    004784CB  |> BB 05000000    MOV EBX,5                                ;  Cases 9,E of switch 004784AA
    004784D0  |. E9 7E000000    JMP FALLOUT2.00478553
    004784D5  |> BB 07000000    MOV EBX,7                                ;  Cases A,C,F,11 of switch 004784AA
    004784DA  |. E9 74000000    JMP FALLOUT2.00478553
    004784DF  |> BB 09000000    MOV EBX,9                                ;  Cases 10,12 of switch 004784AA
    004784E4  |. E9 6A000000    JMP FALLOUT2.00478553
    004784E9  |> BB 0A000000    MOV EBX,0A                               ;  Case D of switch 004784AA
    004784EE  |. EB 63          JMP SHORT FALLOUT2.00478553
    004784F0  |> BB 0C000000    MOV EBX,0C                               ;  Case 13 of switch 004784AA
    004784F5  |. EB 5C          JMP SHORT FALLOUT2.00478553
    004784F7  |> 89E2           MOV EDX,ESP                  ; normal weapon processing here
    004784F9  |. 895424 0C      MOV DWORD PTR SS:[ESP+C],EDX
    004784FD  |. 74 33          JE SHORT FALLOUT2.00478532
    004784FF  |. 8D5424 08      LEA EDX,DWORD PTR SS:[ESP+8]
    00478503  |. 8B40 64        MOV EAX,DWORD PTR DS:[EAX+64]
    00478506  |. E8 FD9B0200    CALL FALLOUT2.004A2108
    0047850B  |. 8D4424 04      LEA EAX,DWORD PTR SS:[ESP+4]
    0047850F  |. 85C0           TEST EAX,EAX
    00478511  |. 74 0B          JE SHORT FALLOUT2.0047851E
    00478513  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
    00478517  |. 8B40 28        MOV EAX,DWORD PTR DS:[EAX+28]
    0047851A  |. 894424 04      MOV DWORD PTR SS:[ESP+4],EAX
    0047851E  |> 837C24 0C 00   CMP DWORD PTR SS:[ESP+C],0
    00478523  |. 74 0D          JE SHORT FALLOUT2.00478532
    00478525  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
    00478529  |. 8B5424 0C      MOV EDX,DWORD PTR SS:[ESP+C]
    0047852D  |. 8B40 2C        MOV EAX,DWORD PTR DS:[EAX+2C]
    00478530  |. 8902           MOV DWORD PTR DS:[EDX],EAX
    00478532  |> 89F2           MOV EDX,ESI
    00478534  |. 89F8           MOV EAX,EDI
    00478536  |. E8 45FDFFFF    CALL FALLOUT2.00478280 ; Get attack_code (?)
    0047853B  |. 83F8 02        CMP EAX,2 ; is it a kick... (?)
    0047853E  |. 74 05          JE SHORT FALLOUT2.00478545
    00478540  |. 83F8 01        CMP EAX,1 ; or a punch? (?) prevents melee bonus from being added to thrown weapons, I think...
    00478543  |. 75 0E          JNZ SHORT FALLOUT2.00478553
    00478545  |> BA 0B000000    MOV EDX,0B
    0047854A  |. 89C8           MOV EAX,ECX
    0047854C  |. E8 F7690300    CALL FALLOUT2.004AEF48  ; If yes, Retrieve PC.Melee Damage Bonus
    00478551  |. 89C5           MOV EBP,EAX
    00478553  |> 8B1424         MOV EDX,DWORD PTR SS:[ESP]    ;  Default case of switch 004784AA - retrieve max damage of attack
    00478556  |. 8B4424 04      MOV EAX,DWORD PTR SS:[ESP+4]  ; retrieve min damage of attack
    0047855A  |. 01EA           ADD EDX,EBP   ; max_damage += bonus_melee_damage
    0047855C  |. 01D8           ADD EAX,EBX   ; min_damage += special unarmed bonus
    0047855E  |. 01DA           ADD EDX,EBX   ; max_damage += special unarmed bonus
    00478560  |. E8 5BAB0200    CALL FALLOUT2.004A30C0 ; return random number between min_dam and max_dam inclusive
    00478565  |> 83C4 10        ADD ESP,10
    00478568  |. 5D             POP EBP
    00478569  |. 5F             POP EDI
    0047856A  |. 5E             POP ESI
    0047856B  |. 59             POP ECX
    0047856C  |. 5B             POP EBX
    0047856D  \. C3             RETN
    
    Cheers,

    -- The Haen.
     
  6. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    Here:
    Code:
    int item_w_damage(sCritter* critter, int type) {
    	sItem* weapon=0;
    	int mindmg=0, maxdmg=0;
    	if(!critter) return 0;
    	switch(type) {
    	case ATKTYPE_LWEP_PRIMARY: case ATKTYPE_LWEP_SECONDARY: case ATKTYPE_LWEP_RELOAD:
    		weapon=inven_left_hand(critter);
    		break;
    	case ATKTYPE_RWEP_PRIMARY: case ATKTYPE_RWEP_SECONDARY: case ATKTYPE_RWEP_RELOAD:
    		weapon=inven_right_hand(critter);
    		break;
    	}
    	if(weapon) {
    		sProto* proto;
    		proto_ptr(weapon->pid, &proto);
    		mindmg=proto->w_min_damage;
    		maxdmg=proto->w_max_damage;
    		if(item_w_subtype(weapon, type) == 1 || item_w_subtype(weapon, type)==2) {
    			maxdmg+=stat_level(critter, STAT_melee_damage);
    		}
    	} else {
    		int bonus=0;
    		switch(type) {
    		case ATKTYPE_STRONGPUNCH: bonus=3; break;
    		case ATKTYPE_HAMMERPUNCH: bonus=5; break;
    		case ATKTYPE_HAYMAKER: bonus=7; break;
    		case ATKTYPE_JAB: bonus=3; break;
    		case ATKTYPE_PALMSTRIKE: bonus=7; break;
    		case ATKTYPE_PIERCINGSTRIKE: bonus=10; break;
    		case ATKTYPE_STRONGKICK: bonus=5; break;
    		case ATKTYPE_SNAPKICK: bonus=7; break;
    		case ATKTYPE_POWERKICK: bonus=9; break;
    		case ATKTYPE_HIPKICK: bonus=7; break;
    		case ATKTYPE_HOOKKICK: bonus=9; break;
    		case ATKTYPE_PIERCINGKICK: bonus=12; break;
    		}
    		maxdmg=stat_level(critter, STAT_melee_damage) + 2 + bonus;
    		mindmg=1 + bonus;
    	}
    	return roll_random(mindmg, maxdmg);
    }
     
  7. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    @Haen
    Could you post the code where the bonus melee damage is calculated?

    I believe I already have the changes I want for the above code you posted, actually very minor to accomplish what I wanted.

    @Timeslip
    Just so I'm clear, the code you posted is the C code equivalent of the Assembly code Haen posted - correct?

    Thanks,
    Glovz
     
  8. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    Yup. (Well, mostly. In the original there's calls to item_hit_with and item_w_damage_min_max, which got inlined, so I left them inline too. It's why the code utterly pointlessly checks that the address of the stack is non-null. :P)
     
  9. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    Cool - though I'm not sure how to edit your code for the small changes I have made so far.

    Take a look:
    Code:
    004783F8   . 7C844700       DD FALLOUT2.0047847C                     ;  Switch table used at 00478475 
    004783FC   . 7C844700       DD FALLOUT2.0047847C 
    00478400   . 83844700       DD FALLOUT2.00478483 
    00478404   . 83844700       DD FALLOUT2.00478483 
    00478408   . 8A844700       DD FALLOUT2.0047848A 
    0047840C   . 8A844700       DD FALLOUT2.0047848A 
    00478410   . 7C844700       DD FALLOUT2.0047847C 
    00478414   . 83844700       DD FALLOUT2.00478483 
    00478418   . C1844700       DD FALLOUT2.004784C1                     ;  Switch table used at 004784B9 
    0047841C   . CB844700       DD FALLOUT2.004784CB 
    00478420   . D5844700       DD FALLOUT2.004784D5 
    00478424   . C1844700       DD FALLOUT2.004784C1 
    00478428   . D5844700       DD FALLOUT2.004784D5 
    0047842C   . E9844700       DD FALLOUT2.004784E9 
    00478430   . CB844700       DD FALLOUT2.004784CB 
    00478434   . D5844700       DD FALLOUT2.004784D5 
    00478438   . DF844700       DD FALLOUT2.004784DF 
    0047843C   . D5844700       DD FALLOUT2.004784D5 
    00478440   . DF844700       DD FALLOUT2.004784DF 
    00478444   . F0844700       DD FALLOUT2.004784F0 
    00478448  /$ 53             PUSH EBX 
    00478449  |. 51             PUSH ECX 
    0047844A  |. 56             PUSH ESI 
    0047844B  |. 57             PUSH EDI 
    0047844C  |. 55             PUSH EBP 
    0047844D  |. 83EC 10        SUB ESP,10 
    00478450  |. 89C1           MOV ECX,EAX  ; pointer to critter 
    00478452  |. 89D6           MOV ESI,EDX  ; hit_mode (see define.h hit_modes > 7 are apparently special unarmed attacks) 
    00478454  |. 31D2           XOR EDX,EDX 
    00478456  |. 31DB           XOR EBX,EBX 
    00478458  |. 31ED           XOR EBP,EBP 
    0047845A  |. 891424         MOV DWORD PTR SS:[ESP],EDX   ; set damage max = 0 
    0047845D  |. 895424 04      MOV DWORD PTR SS:[ESP+4],EDX ; set damage min = 0 
    00478461  |. 85C0           TEST EAX,EAX           ; sanity check for null critter pointer 
    00478463  |. 0F84 FC000000  JE FALLOUT2.00478565   ; if null pointer exit function with value of 0 
    00478469  |. 74 21          JE SHORT FALLOUT2.0047848C ; ??? -- This is unreacheable code 
    0047846B  |. 83FE 07        CMP ESI,7 ; is hit_mode a special unarmed attack? 
    0047846E  |. 77 1A          JA SHORT FALLOUT2.0047848A ; process unarmed attack if yes 
    00478470  |. 89F7           MOV EDI,ESI 
    00478472  |. C1E7 02        SHL EDI,2 
    00478475  |. 2E:FFA7 F88347>JMP DWORD PTR CS:[EDI+4783F8] ; Otherwise, detect from which slot attack was made and get item pointer to it 
    0047847C  |> E8 3B97FFFF    CALL FALLOUT2.00471BBC   ; weapon in left slot, get pointer to it 
    00478481  |. EB 05          JMP SHORT FALLOUT2.00478488 
    00478483  |> E8 E896FFFF    CALL FALLOUT2.00471B70   ; weapon in right slot, get pointer to it 
    00478488  |> 89C2           MOV EDX,EAX 
    0047848A  |> 89D0           MOV EAX,EDX  ; normal punch, kick, or special unarmed attack processing starts here 
    0047848C  |> 89C7           MOV EDI,EAX 
    0047848E  |. 85C0           TEST EAX,EAX        ; is left/right slot empty? 
    00478490  |. 75 65          JNZ SHORT FALLOUT2.004784F7 ; skip ahead if yes 
    00478492  |. BA 01000000    MOV EDX,1                        ; otherwise, no weapons used, so set min_unarmed_damage to 1 
    00478497  |. 89C8           MOV EAX,ECX 
    00478499  |. 895424 04      MOV DWORD PTR SS:[ESP+4],EDX     ; store min_unarmed_damage 
    0047849D  |. BA 0B000000    MOV EDX,0B 
    004784A2  |. E8 A16A0300    CALL FALLOUT2.004AEF48  ; Retrieve PC.Melee Damage Bonus 
    
    
    // Add this line here       ADD DWORD PTR SS:[ESP+4],EAX        ; min_unarmed_damage += bonus_melee_damage 
    
    
    004784A7  |. 83C0 02        ADD EAX,2               ; max_unarmed_damage = bonus_melee_damage + 2 
    004784AA  |. 83EE 08        SUB ESI,8      ;  Switch (cases 8..13), also if hit_mode == 4, 5 (punch, kick), this will go back to 0047848A, but now with nonzero EDX value 
    004784AD  |. 890424         MOV DWORD PTR SS:[ESP],EAX  ; store max_unarmed_damage 
    004784B0  |. 83FE 0B        CMP ESI,0B 
    004784B3  |. 0F87 9A000000  JA FALLOUT2.00478553 
    004784B9  |. 2E:FF24B5 1884>JMP DWORD PTR CS:[ESI*4+478418] ; processing special unarmed attack bonus 
    004784C1  |> BB 03000000    MOV EBX,3                                ;  Cases 8,B of switch 004784AA 
    004784C6  |. E9 88000000    JMP FALLOUT2.00478553 
    004784CB  |> BB 05000000    MOV EBX,5                                ;  Cases 9,E of switch 004784AA 
    004784D0  |. E9 7E000000    JMP FALLOUT2.00478553 
    004784D5  |> BB 07000000    MOV EBX,7                                ;  Cases A,C,F,11 of switch 004784AA 
    004784DA  |. E9 74000000    JMP FALLOUT2.00478553 
    004784DF  |> BB 09000000    MOV EBX,9                                ;  Cases 10,12 of switch 004784AA 
    004784E4  |. E9 6A000000    JMP FALLOUT2.00478553 
    004784E9  |> BB 0A000000    MOV EBX,0A                               ;  Case D of switch 004784AA 
    004784EE  |. EB 63          JMP SHORT FALLOUT2.00478553 
    004784F0  |> BB 0C000000    MOV EBX,0C                               ;  Case 13 of switch 004784AA 
    004784F5  |. EB 5C          JMP SHORT FALLOUT2.00478553 
    004784F7  |> 89E2           MOV EDX,ESP                  ; normal weapon processing here 
    004784F9  |. 895424 0C      MOV DWORD PTR SS:[ESP+C],EDX 
    004784FD  |. 74 33          JE SHORT FALLOUT2.00478532 
    004784FF  |. 8D5424 08      LEA EDX,DWORD PTR SS:[ESP+8] 
    00478503  |. 8B40 64        MOV EAX,DWORD PTR DS:[EAX+64] 
    00478506  |. E8 FD9B0200    CALL FALLOUT2.004A2108 
    0047850B  |. 8D4424 04      LEA EAX,DWORD PTR SS:[ESP+4] 
    0047850F  |. 85C0           TEST EAX,EAX 
    00478511  |. 74 0B          JE SHORT FALLOUT2.0047851E 
    00478513  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8] 
    00478517  |. 8B40 28        MOV EAX,DWORD PTR DS:[EAX+28] 
    0047851A  |. 894424 04      MOV DWORD PTR SS:[ESP+4],EAX 
    0047851E  |> 837C24 0C 00   CMP DWORD PTR SS:[ESP+C],0 
    00478523  |. 74 0D          JE SHORT FALLOUT2.00478532 
    00478525  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8] 
    00478529  |. 8B5424 0C      MOV EDX,DWORD PTR SS:[ESP+C] 
    0047852D  |. 8B40 2C        MOV EAX,DWORD PTR DS:[EAX+2C] 
    00478530  |. 8902           MOV DWORD PTR DS:[EDX],EAX 
    00478532  |> 89F2           MOV EDX,ESI 
    00478534  |. 89F8           MOV EAX,EDI 
    00478536  |. E8 45FDFFFF    CALL FALLOUT2.00478280 ; Get attack_code (?) 
    0047853B  |. 83F8 02        CMP EAX,2 ; is it a kick... (?) 
    0047853E  |. 74 05          JE SHORT FALLOUT2.00478545 
    00478540  |. 83F8 01        CMP EAX,1 ; or a punch? (?) prevents melee bonus from being added to thrown weapons, I think... 
    00478543  |. 75 0E          JNZ SHORT FALLOUT2.00478553 
    00478545  |> BA 0B000000    MOV EDX,0B 
    0047854A  |. 89C8           MOV EAX,ECX 
    0047854C  |. E8 F7690300    CALL FALLOUT2.004AEF48  ; If yes, Retrieve PC.Melee Damage Bonus 
    00478551  |. 89C5           MOV EBP,EAX 
    00478553  |> 8B1424         MOV EDX,DWORD PTR SS:[ESP]    ;  Default case of switch 004784AA - retrieve max damage of attack 
    00478556  |. 8B4424 04      MOV EAX,DWORD PTR SS:[ESP+4]  ; retrieve min damage of attack 
    
    
    // Add this line here       ADD EAX,EBP   ; min_damage += bonus_melee_damage
    
    
    0047855A  |. 01EA           ADD EDX,EBP   ; max_damage += bonus_melee_damage 
    0047855C  |. 01D8           ADD EAX,EBX   ; min_damage += special unarmed bonus 
    0047855E  |. 01DA           ADD EDX,EBX   ; max_damage += special unarmed bonus 
    00478560  |. E8 5BAB0200    CALL FALLOUT2.004A30C0 ; return random number between min_dam and max_dam inclusive 
    00478565  |> 83C4 10        ADD ESP,10 
    00478568  |. 5D             POP EBP 
    00478569  |. 5F             POP EDI 
    0047856A  |. 5E             POP ESI 
    0047856B  |. 59             POP ECX 
    0047856C  |. 5B             POP EBX 
    0047856D  \. C3             RETN 
    
    EDIT:
    Changed as per Timeslip's comment.
     
  10. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    The second change is fine. The first isn't; you haven't given the arguments to stat_level. It'll just crash. :P

    In any case, there's no point calling a function twice to get the same value. Just stick a 'add [esp+4], eax' in at 0x4784A7.

    tbh, given how simple and self contained that function is, if you want to change it I'd rather hookscript it than make hardcoded changes to it.
     
  11. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    Thank you Timeslip for the correction.

    If you feel you can help and make this easier, then great! But just note that I'm not great with C, but maybe Haen is. Togther hopefully we find the best solution for implementing the changes.

    Thanks,
    Glovz

    EDIT:
    There is also one other portion of code I asked Haen to post - the section that calculates the bonus melee damage. There is still one change I would like to attempt making there.
     
  12. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    That's not another portion of the code; it's in the bit that's already posted. Or do you mean something else? :?
     
  13. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    I believe I understood the code posted correctly. But please slap me if I'm wrong again. :?

    This line --- CALL FALLOUT2.004AEF48 ; Retrieve PC.Melee Damage Bonus --- is a call out to a portion of the code not listed previously and I assume returns a value calculated against other criteria.

    Haen described it as:
    Code:
    bonus_melee_damage = max(player_strength - 5, 1) + heavy_handed_bonus + (2 * rank_of_bonus_hth_damage_perk)
    I want to change it to:
    Code:
    bonus_melee_damage = max(player_strength - 5, 1 + (2 * rank_of_bonus_hth_damage_perk)) + heavy_handed_bonus
    This is the last piece of the puzzle.
     
  14. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    That's the stat_level function. Nothing special there; it just returns a stat of a given critter. If you want to change a critters unarmed damage stat, there are a heck of a lot easier ways of doing it than fiddling with the exe. (i.e. the set_critter_stat script function.)

    Edit: Here's the C version. I don't have the asm at hand sorry.

    Code:
    int stat_level(sCritter* critter, DWORD statID) {
    	if(statID>=STAT_real_max_stat) return 0;
    	if(statID==STAT_current_hp) return critter_get_hits(critter);
    	if(statID==STAT_current_poison) return critter_get_poison(critter);
    	if(statID==STAT_current_rad) return critter_get_rads(critter);
    	int stat=stat_get_base(critter, statID) + stat_get_bonus(critter, statID);
    	if(statID==STAT_ac&&GetCombatState()==1&&critter!=combat_whose_turn()) {
    		int apmult=1;
    		if(perk_level(critter, PERK_hth_evade_perk)) {
    			sCritter* inven=inven_right_hand(obj_dude());
    			if(!inven||(item_get_type(inven)!=3&&item_w_anim_code(inven)==0)) {
    				inven=inven_left_hand(obj_dude());
    				if(!inven||(item_get_type(inven)!=3&&item_w_anim_code(inven)==0)) {
    					apmult*=2;
    				}
    				stat+=skill_level(critter, SKILL_UNARMED_COMBAT)/12;
    			}
    		}
    		stat+=critter->c_CurrentAP*apmult;
    	}
    	if(statID==STAT_pe&&critter->c_InjuredLimbs&CRITTER_EYEDAMAGE) stat-=5;
    	if(statID==STAT_age) stat+=game_time()/0x12CC0300;
    	if(statID==STAT_max_ap) {
    		int burden=stat_level(critter, STAT_carry_amt)<item_total_weight(critter);
    		if(burden<0) {
    			stat-=1 + (-burden)/40;
    		}
    	}
    	if(critter==obj_dude()) {
    		switch(statID) {
    		case STAT_st:
    			if(perk_level(critter, PERK_gain_strength_perk)) stat++;
    			if(perk_level(critter, PERK_adrenaline_rush_perk)) {
    				if(stat_level(critter, STAT_max_hp)/2 > stat_level(critter, STAT_current_hp)) stat++;
    			}
    			break;
    		case STAT_pe:
    			if(perk_level(critter, PERK_gain_perception_perk)) stat++;
    			break;
    		case STAT_en:
    			if(perk_level(critter, PERK_gain_endurance_perk)) stat++;
    			break;
    		case STAT_ch:
    			if(perk_level(critter, PERK_gain_charisma_perk)) stat++;
    			if(inven_right_hand(obj_dude())->PID==0x1b1||inven_left_hand(obj_dude())->PID==0x1b1) stat++;
    			break;
    		case STAT_iq:
    			if(perk_level(critter, PERK_gain_intelligence_perk)) stat++;
    			break;
    		case STAT_ag:
    			if(perk_level(critter, PERK_gain_agility_perk)) stat++;
    			break;
    		case STAT_lu:
    			if(perk_level(critter, PERK_gain_luck_perk)) stat++;
    			break;
    		case STAT_rad_resist:
    		case STAT_poison_resist:
    			if(perk_level(critter, PERK_vault_city_inoculations_perk)) stat+=10;
    			break;
    		case STAT_dmg_resist:
    		case STAT_dmg_resist_explosion:
    			if(perk_level(critter, PERK_dermal_armor_perk)) stat+=5;
    			if(perk_level(critter, PERK_dermal_enhancement_perk)) stat+=10;
    			break;
    		case STAT_dmg_resist_laser:
    		case STAT_dmg_resist_fire:
    		case STAT_dmg_resist_plasma:
    			if(perk_level(critter, PERK_phoenix_armor_perk)) stat+=5;
    			if(perk_level(critter, PERK_phoenix_enhancement_perk)) stat+=10;
    			break;
    		case STAT_max_hp:
    			if(perk_level(critter, PERK_alcohol_hp_bonus1_perk)) stat+=2;
    			if(perk_level(critter, PERK_alcohol_hp_bonus2_perk)) stat+=4;
    			if(perk_level(critter, PERK_alcohol_hp_neg1_perk)) stat-=2;
    			if(perk_level(critter, PERK_alcohol_hp_neg2_perk)) stat-=4;
    			if(perk_level(critter, PERK_autodoc_hp_bonus1_perk)) stat+=2;
    			if(perk_level(critter, PERK_autodoc_hp_bonus2_perk)) stat+=4;
    			if(perk_level(critter, PERK_autodoc_hp_neg1_perk)) stat-=2;
    			if(perk_level(critter, PERK_autodoc_hp_neg2_perk)) stat-=4;
    			break;
    		}
    	}
    	if(stat>stat_data[statID].Maximum) stat=stat_data[statID].Maximum;
    	if(stat<stat_data[statID].Minimum) stat=stat_data[statID].Minimum;
    	return stat;
    }
    Edit2: Actually bothering to read that, what you want to change isn't in there anyway. Try stat_recalc_derived at 0x4AF6FC.
     
  15. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    After re-evaluating the last change I wanted to make, I find it doesn't have the affect I wanted and breaks my own rule of applying bonuses only after primarily values are calculated/selected.

    With that said then I think the only change necessary is the one I made earlier today. :)

    I still want to have Haen's input.

    Haen did you get a chance to evaluate the code I posted from crazycc back on page 1 of this thread? crazycc claimed it added the HtH evade perk to both unarmed and melee attacks.
     
  16. Haenlomal

    Haenlomal It Wandered In From the Wastes

    178
    Sep 25, 2003
    Thanks to Timeslip for all his input, especially the translation of the assembly code to something like C. I do have RecStudio (btw, is there anything better out there?), but haven't had the time to really dig into the code like Timeslip obviously had. It's also been a few years since I went from being a coder to a business major, so my technical skills are more than a trifle rusty. :oops:

    Time to answer a few overdue questions:

    @Glovz:

    I've looked at crazycc's changes. It seems like they do what he claims it does. I don't think it would collide with anything we're doing, since it doesn't touch anything to do with melee damage.

    @Magnus:

    Since I only have one monitor myself, I also run into the same problem as you did with the not returning to desktop thing. I do something similar to Glovz: I inject assembly code into the damage function and force it to return values I want to isolate -- most of the time, I make the damage function return the values I want instead of the true damage.

    That said, I can usually tell what's going on just by looking at the code. For one thing, I can read at a rate of 5000 words per minute, and this translates directly to me being able to rapidly assimilate code while still maintaining their relative position and importance to each other. I also know that enum values for most weapons, armors, dmg_type, atk_type and anim_codes by heart. So, seeing what the function is and looking at its boundary checking conditions, I can usually make fairly good guesses as to what's going on, and I inject code to verify my claims. If I turn out to be wrong, it's usually not too difficult to work out from that point on what's really happening.

    I would much rather have a dual monitor setup -- would make my work much much easier -- but like Glovz said, it's also a very time consuming process for me.

    @Nevill and Glovz (re: tweaked damage formulas)

    To get a grasp of the issue, I've looked through what the Fallout 2 manual says about Melee Damage, Heavy Handed Trait, Bonus HtH Damage perk, and Bonus Ranged Damage perk, along with the in-game descriptions of each of them. I've also thought about how HtH combat works in real life based on my own personal point-of-view as a martial artist, effective ways to model said behaviour. Here's my opinion on all of it.

    The manual was pretty clear that Melee Damage is not really a bonus damage at all, but an increase of potential damage. Therefore, it only increases the maximum damage level. In this, I think I am in agreement: it doesn't matter how strong or accomplished a person is. Sometimes, a blow dealt by the fists or staff just doesn't seem to do much damage because of the way the blow is landed. Kung-fu movies notwithstanding, it's actually extremely difficult to strike with maximum strength and effectiveness at the precise point of impact every time, so you are going to experience variations in damage output. So I would leave its current implementation alone.

    Similar comments can be said about the Heavy Handed Trait, though for game balance purposes, I might consider applying it to minimum damage. As it stands, you gain an average of +2 melee damage, while you no longer have access to any of the higher level critical effects. Not really a worthwhile trait to go for under any circumstances. Applying it to minimum damage makes the Trait a bit more palatable, but it still, um, sucks. :P I know Per calls it "Potentially useful" trait in his famed walkthrough, but personally, I'd classify it as a "Traits to avoid".

    When it comes to Bonus HtH Damage, though, I'm starting to think that its implementation is an engine bug. Both the in-game and manual descriptions seem to imply that it works in the same fashion as Bonus Ranged Damage. As such, they should be treated the same way. I guess it's possible the bug is the other way around (i.e. Bonus HtH Damage is working as expected -- it's Bonus Ranged Damage that's being handled improperly), but it doesn't make sense that way.

    So personally, I would amend the HtH damage formula to the following:

    Code:
    raw_HtH_damage = random(min_dam + special_unarmed_bonus + 2*rank_of_HtH_dam_perk, max_dam + melee_damage + heavy_handed_bonus + special_unarmed_bonus + 2*rank_of_HtH_dam_perk)
    
    Cheers,

    -- The Haen.
     
  17. Nevill

    Nevill First time out of the vault

    85
    Mar 14, 2007
    That was more or less what I was proposing. It would be nice if you defined 'melee_damage', though, to see if its really the case.
     
  18. Haenlomal

    Haenlomal It Wandered In From the Wastes

    178
    Sep 25, 2003
    Melee Damage has been previously defined as:

    Code:
    max(strength - 5, 1)
    
    This means that Melee Damage can take on any value from 1 to 5 inclusive. You can see its effects directly if you play around a bit with the new character creation screen.

    -- The Haen.
     
  19. Timeslip

    Timeslip Water Chip? Been There, Done That
    Modder

    921
    Aug 15, 2007
    Yes, your own brain. :P

    Seriously, I'm yet to see an automatic decompiler that's useful on real-world optimized code. You're far better off doing it by hand; it takes longer, but at least the result actually stands a reasonable chance of being right.
     
  20. Glovz

    Glovz Vault Dweller
    Modder

    736
    Sep 16, 2005
    To clarify things, this is what everyone would like to aim for:
    Melee Damage Scale
    Code:
    melee_damage = max(player_strength - 5, 1)
    Weapon Melee Damage
    Code:
    raw_damage = random(min_damage_of_melee_weapon, max_damage_of_melee_weapon + melee_damage)
    Unarmed Melee Damage (equivalent to Haen's formula)
    Code:
    raw_damage = random(1, 2 + melee_damage + heavy_handed_bonus) + special_unarmed_bonus + (2*rank_of_HtH_dam_perk)
    Does everyone agree? I think I can live with this. :D

    Now how to implement this? :?