Site  •  Wiki  •  FAQ  •  Login

Modifying unit speed and weapon cooldown

<<

RadiganP

Posts: 10

Joined: December 8th, 2010, 1:57 pm

Post October 31st, 2012, 1:30 am

Modifying unit speed and weapon cooldown

Are you looking for a way to change how speed upgrades work? Do you want to control the effects of Ensnare on weapon cooldown? Then this article is for you.

I wrote several functions that replace StarCraft's built-in unit speed/attack cooldown functions. The ones presented here merely recreate StarCraft's internal logic; you can replace it with your own C++ code. Do NOT change the function prologue/epilogue unless you know what you are doing!

0. Preparation

The functions access the following arrays/enums:

  • Offsets to internal DAT arrays: UnitsDat_Graphic, FlingyDat_Acceleration, FlingyDat_TurnSpeed, WeaponsDat_Cooldown
  • Predefined enumerations: SF_SpeedUpgrade, SF_CooldownUpgrade, Protoss_Scout, Protoss_Hero_Mojo, Protoss_Hero_Artanis
I will post ASAP C++ header files that contain these arrays. In the meantime, try looking at BWAPI's Offsets.h, UnitStatusFlags.h, and UnitID.h.

To make StarCraft actually use the functions below, you must add a call to JmpCallPatch() in qdp.cpp for each function, like this:
  Code:

    
//Note: this is inside the InitializePlugin() function
    //Syntax: JmpCallPatch(function_name, function_inject_address);
    JmpCallPatch(GetModifiedSpeed, GetModifiedSpeedInject);
 


1. Modifying unit speed

This code goes in game.h:
  Code:

DWORD const GetModifiedSpeedInject        
= 0x0047B5F0;

void __declspec(naked) GetModifiedSpeed() {
    UNIT *unit;
    DWORD speed;
    __asm {
        PUSHAD
        MOV ebp
, esp
        MOV unit
, edx
        MOV speed
, eax
    
}

    //C++ code goes here
    int speedModifier;
    speedModifier = (unit->stimTimer ? 1 : 0) - (unit->ensnareTimer ? 1 : 0)
        + (unit->status & SF_SpeedUpgrade ? 1 : 0);
    if (speedModifier > 0) {
        if (unit->unitId == Protoss_Scout || unit->unitId == Protoss_Hero_Mojo || unit->unitId == Protoss_Hero_Artanis)
            speed = 1707;
        else {
            speed += speed >> 1;
            speed = speed > 853 ? speed : 853;
        }
    }
    else if (speedModifier < 0)
        speed >>= 1;
    //End of C++ code

    __asm {
        MOV eax, speed
        MOV 
[esp + 28], eax
        POPAD
        RET
    
}
}
 


2. Modifying acceleration

This code goes in game.h:
  Code:

DWORD const GetModifiedAccelerationInject    
= 0x0047B8A0;

void __declspec(naked) GetModifiedAcceleration() {
    UNIT *unit;
    DWORD acceleration;
    __asm {
        PUSHAD
        MOV ebp
, esp
        MOV unit
, ecx
    
}

    //C++ code goes here
    acceleration = FlingyDat_Acceleration[UnitsDat_Graphic[unit->unitId]];
    int speedModifier;
    speedModifier = (unit->stimTimer ? 1 : 0) - (unit->ensnareTimer ? 1 : 0)
        + (unit->status & SF_SpeedUpgrade ? 1 : 0);
    if (speedModifier > 0)
        acceleration *= 2;
    else if (speedModifier < 0)
        acceleration -= acceleration >> 2;
    //End of C++ code

    __asm {
        MOV eax, acceleration
        MOV 
[esp + 28], eax
        POPAD
        RET
    
}
}
 


3. Modifying turn speed
Note: Turn speed is incorrectly known as "turn radius" in DatEdit.

This code goes in game.h:
  Code:

DWORD const GetModifiedTurnSpeedInject    
= 0x0047B850;

void __declspec(naked) GetModifiedTurnSpeed() {
    UNIT *unit;
    DWORD turnSpeed;
    __asm {
        PUSHAD
        MOV ebp
, esp
        MOV unit
, ecx
    
}

    //C++ code goes here
    turnSpeed = FlingyDat_TurnSpeed[UnitsDat_Graphic[unit->unitId]];
    int speedModifier;
    speedModifier = (unit->stimTimer ? 1 : 0) - (unit->ensnareTimer ? 1 : 0)
        + (unit->status & SF_SpeedUpgrade ? 1 : 0);
    if (speedModifier > 0)
        turnSpeed *= 2;
    else if (speedModifier < 0)
        turnSpeed -= turnSpeed >> 2;
    //End of C++ code

    __asm {
        MOV eax, turnSpeed
        MOV 
[esp + 28], eax
        POPAD
        RET
    
}
}
 


4. Modifying attack cooldown

This code goes in game.h:
  Code:

DWORD GetModifiedWeaponCooldownInject    
= 0x00475DC0;

void __declspec(naked) GetModifiedWeaponCooldown() {
    UNIT *unit;
    BYTE weaponId;
    DWORD cooldown;
    __asm {
        PUSHAD
        MOV ebp
, esp
        MOV unit
, esi
        MOV weaponId
, al
    
}

    //C++ code goes here
    cooldown = WeaponsDat_Cooldown[weaponId];

    if (unit->acidSporeCount) {
        DWORD increaseAmt = cooldown >> 3;
        if (increaseAmt < 3) increaseAmt = 3;
        cooldown += increaseAmt * unit->acidSporeCount;
    }

    int cooldownModifier;
    cooldownModifier = (unit->stimTimer ? 1 : 0) - (unit->ensnareTimer ? 1 : 0)
        + (unit->status & SF_CooldownUpgrade ? 1 : 0);
    if (cooldownModifier > 0)
        cooldown >>= 1;
    else if (cooldownModifier < 0)
        cooldown += cooldown >> 2;

    if (cooldown > 250) cooldown = 250;
    else if (cooldown < 5) cooldown = 5;
    //End of C++ code

    __asm {
        MOV eax, cooldown
        MOV 
[esp + 28], eax
        POPAD
        RET
    
}
}
 
<<

Hercanic

User avatar

Site Admin

Posts: 478

Joined: June 6th, 2009, 12:25 am

Location: Korea

Post November 19th, 2012, 10:14 pm

Re: Modifying unit speed and weapon cooldown

Very useful stuff here! One quick note for anyone copy/pasting this code: unfortunately the forum's [code] BBcode replaces tabs with spaces, which can cause problems.

Return to Plugins

Who is online

Users browsing this forum: No registered users and 1 guest

cron
phpBBST Software