Skip to content

Commit

Permalink
Fix beyond-all-reason#817, add Spring.SetUnitShieldRechargeDelay
Browse files Browse the repository at this point in the history
  • Loading branch information
sprunk committed Jun 10, 2023
1 parent 0966eb9 commit c4649bb
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 2 deletions.
5 changes: 5 additions & 0 deletions doc/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ Lua:
- add `Spring.SelectUnit(unitID, bool append = false) -> nil`, single-unit
version of SelectUnit{Array,Map} that doesn't require a table
- add `Spring.DeselectUnit(unitID) -> nil`, deselects a unit
- add `Spring.SetUnitShieldRechargeDelay(unitID, [weaponNum], [seconds]) -> nil`. Resets a unit's
shield regeneration delay. The weapon number is optional if the unit has a single shield. The
timer value is also optional, if you leave it nil it will emulate a weapon hit. Note that a
weapon hit (both via nil here, and "real" hits) will never decrease the remaining timer, though
it can increase it. An explicit numerical value always sets the timer to that many seconds.
- add `wupget:Unit{Entered,Left}Underwater(unitID, unitDefID, teamID)`. Works very similar
to the existing Water callins, but EnteredWater applies when the unit dips its toes in water
while EnteredUnderwater applies when the unit is completely submerged.
Expand Down
37 changes: 37 additions & 0 deletions rts/Lua/LuaSyncedCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ bool LuaSyncedCtrl::PushEntries(lua_State* L)
REGISTER_LUA_CFUNC(SetUnitBlocking);
REGISTER_LUA_CFUNC(SetUnitCrashing);
REGISTER_LUA_CFUNC(SetUnitShieldState);
REGISTER_LUA_CFUNC(SetUnitShieldRechargeDelay);
REGISTER_LUA_CFUNC(SetUnitFlanking);
REGISTER_LUA_CFUNC(SetUnitTravel);
REGISTER_LUA_CFUNC(SetUnitFuel);
Expand Down Expand Up @@ -2925,6 +2926,42 @@ int LuaSyncedCtrl::SetUnitShieldState(lua_State* L)
return 0;
}

/***
* @function Spring.SetUnitShieldRechargeDelay
* @number unitID
* @number[opt] weaponID (optional if the unit only has one shield)
* @number[opt] rechargeTime (in seconds; emulates a regular hit if nil)
* @treturn nil
*/
int LuaSyncedCtrl::SetUnitShieldRechargeDelay(lua_State* L)
{
const auto unit = ParseUnit(L, __func__, 1);
if (unit == nullptr)
return 0;

auto shield = static_cast <CPlasmaRepulser*> (unit->shieldWeapon);
if (lua_isnumber(L, 2)) {
const size_t index = lua_tointeger(L, 2) - LUA_WEAPON_BASE_INDEX;
if (index < unit->weapons.size())
shield = dynamic_cast <CPlasmaRepulser*> (unit->weapons[index]);
}
if (shield == nullptr)
return 0;

if (lua_isnumber(L, 3)) {
const auto seconds = lua_tofloat(L, 3);
const auto frames = static_cast <int> (seconds * GAME_SPEED);
shield->SetRechargeDelay(frames, true);
} else {
/* Note, overwrite set to false on purpose. This is to emulate a regular
* weapon hit. This lets a sophisticated shield handler gadget coexist
* with a basic "emulate hits" gadget without the latter having to care.
* You can put the weaponDef value explicitly if you want to overwrite. */
shield->SetRechargeDelay(shield->weaponDef->shieldRechargeDelay, false);
}

return 0;
}

/***
* @function Spring.SetUnitFlanking
Expand Down
1 change: 1 addition & 0 deletions rts/Lua/LuaSyncedCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class LuaSyncedCtrl
static int SetUnitBlocking(lua_State* L);
static int SetUnitCrashing(lua_State* L);
static int SetUnitShieldState(lua_State* L);
static int SetUnitShieldRechargeDelay(lua_State* L);
static int SetUnitFlanking(lua_State* L);
static int SetUnitTravel(lua_State* L);
static int SetUnitFuel(lua_State* L);
Expand Down
11 changes: 9 additions & 2 deletions rts/Sim/Weapons/PlasmaRepulser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,18 @@ void CPlasmaRepulser::Update()
sscPool.UpdateCollection(this);
}

void CPlasmaRepulser::SetRechargeDelay(int delay, bool overwrite)
{
if (overwrite)
rechargeDelay = delay;
else
rechargeDelay = std::max(rechargeDelay, delay);
}

// Returns true if the projectile is destroyed.
bool CPlasmaRepulser::IncomingProjectile(CWeaponProjectile* p, const float3& hitPos)
{
const int defHitFrames = weaponDef->visibleShieldHitFrames;
const int defRechargeDelay = weaponDef->shieldRechargeDelay;

// gadget handles the collision event, don't touch the projectile
// start-pos only makes sense for beams, pass current p->pos here
Expand All @@ -187,7 +194,7 @@ bool CPlasmaRepulser::IncomingProjectile(CWeaponProjectile* p, const float3& hit
if (teamHandler.Team(owner->team)->res.energy < weaponDef->shieldEnergyUse)
return false;

rechargeDelay = defRechargeDelay;
SetRechargeDelay(weaponDef->shieldRechargeDelay, false);

if (weaponDef->shieldRepulser) {
// bounce the projectile
Expand Down
1 change: 1 addition & 0 deletions rts/Sim/Weapons/PlasmaRepulser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class CPlasmaRepulser: public CWeapon


void SetEnabled(bool b) { isEnabled = b; }
void SetRechargeDelay(int delay, bool overwrite);
void SetCurPower(float p) { curPower = p; }

bool IsEnabled() const { return isEnabled; }
Expand Down

0 comments on commit c4649bb

Please sign in to comment.