Compare commits

...

3 Commits

Author SHA1 Message Date
gsemaj
02fd17c0e7
Implement leech 2023-08-13 18:27:18 -07:00
gsemaj
da33c5c30f
Make clearBuffs memory-safe
improperly erasing during iteration oops
2023-08-13 18:26:30 -07:00
gsemaj
478ae3d996
Break if player dies from buff combat tick 2023-08-13 14:26:05 -07:00
2 changed files with 35 additions and 16 deletions

View File

@ -85,8 +85,26 @@ static SkillResult handleSkillDamageNDebuff(SkillData* skill, int power, ICombat
} }
static SkillResult handleSkillLeech(SkillData* skill, int power, ICombatant* source, ICombatant* target) { static SkillResult handleSkillLeech(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
// TODO abilities EntityRef sourceRef = source->getRef();
return SkillResult(); int heal = skill->values[0][power];
int healed = source->heal(sourceRef, heal);
int damage = heal * 2;
int dealt = target->takeDamage(sourceRef, damage);
sSkillResult_Leech result{};
result.Damage.eCT = target->getCharType();
result.Damage.iID = target->getID();
result.Damage.bProtected = dealt <= 0;
result.Damage.iDamage = dealt;
result.Damage.iHP = target->getCurrentHP();
result.Heal.eCT = result.Damage.eCT;
result.Heal.iID = result.Damage.iID;
result.Heal.iHealHP = healed;
result.Heal.iHP = source->getCurrentHP();
return SkillResult(sizeof(sSkillResult_Leech), &result);
} }
static SkillResult handleSkillBuff(SkillData* skill, int power, ICombatant* source, ICombatant* target) { static SkillResult handleSkillBuff(SkillData* skill, int power, ICombatant* source, ICombatant* target) {

View File

@ -61,15 +61,14 @@ void Player::removeBuff(int buffId, BuffClass buffClass) {
} }
void Player::clearBuffs(bool force) { void Player::clearBuffs(bool force) {
for(auto buff : buffs) { auto it = buffs.begin();
if(!force) { while(it != buffs.end()) {
removeBuff(buff.first); Buff* buff = (*it).second;
} else { if(!force) buff->clear();
delete buff.second; delete buff;
it = buffs.erase(it);
} }
} }
buffs.clear();
}
bool Player::hasBuff(int buffId) { bool Player::hasBuff(int buffId) {
auto buff = buffs.find(buffId); auto buff = buffs.find(buffId);
@ -169,6 +168,8 @@ void Player::step(time_t currTime) {
// buffs // buffs
for(auto buffEntry : buffs) { for(auto buffEntry : buffs) {
buffEntry.second->combatTick(currTime); buffEntry.second->combatTick(currTime);
if(!isAlive())
break; // unsafe to keep ticking if we're dead
} }
} }
#pragma endregion #pragma endregion
@ -215,15 +216,14 @@ void CombatNPC::removeBuff(int buffId, BuffClass buffClass) {
} }
void CombatNPC::clearBuffs(bool force) { void CombatNPC::clearBuffs(bool force) {
for(auto buff : buffs) { auto it = buffs.begin();
if(!force) { while(it != buffs.end()) {
removeBuff(buff.first); Buff* buff = (*it).second;
} else { if(!force) buff->clear();
delete buff.second; delete buff;
it = buffs.erase(it);
} }
} }
buffs.clear();
}
bool CombatNPC::hasBuff(int buffId) { bool CombatNPC::hasBuff(int buffId) {
auto buff = buffs.find(buffId); auto buff = buffs.find(buffId);
@ -957,6 +957,7 @@ static void playerTick(CNServer *serv, time_t currTime) {
auto it = plr->buffs.begin(); auto it = plr->buffs.begin();
while(it != plr->buffs.end()) { while(it != plr->buffs.end()) {
Buff* buff = (*it).second; Buff* buff = (*it).second;
//buff->combatTick() gets called in Player::step
buff->tick(currTime); buff->tick(currTime);
if(buff->isStale()) { if(buff->isStale()) {
// garbage collect // garbage collect