The Sleep, Stun and Snare powers now affect mobs.

They currently don't expire after a set amount of time.
Attacking a sleeping monster does wake it up, but doesn't remove the
debuff status client-side yet.
This commit is contained in:
dongresource 2020-09-22 22:22:10 +02:00
parent 95a79ec815
commit c722044bf5
3 changed files with 27 additions and 3 deletions

View File

@ -61,6 +61,9 @@ void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
mob->appearanceData.iHP -= 100; mob->appearanceData.iHP -= 100;
// wake up sleeping monster
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
if (mob->appearanceData.iHP <= 0) if (mob->appearanceData.iHP <= 0)
killMob(sock, mob); killMob(sock, mob);
@ -132,6 +135,7 @@ void MobManager::giveReward(CNSocket *sock) {
void MobManager::killMob(CNSocket *sock, Mob *mob) { void MobManager::killMob(CNSocket *sock, Mob *mob) {
mob->state = MobState::DEAD; mob->state = MobState::DEAD;
mob->appearanceData.iConditionBitFlag = 0;
mob->killedTime = getTime(); // XXX: maybe introduce a shard-global time for each step? mob->killedTime = getTime(); // XXX: maybe introduce a shard-global time for each step?
std::cout << "killed mob " << mob->appearanceData.iNPC_ID << std::endl; std::cout << "killed mob " << mob->appearanceData.iNPC_ID << std::endl;
@ -188,6 +192,10 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
int delay = (int)mob->data["m_iDelayTime"] * 1000; int delay = (int)mob->data["m_iDelayTime"] * 1000;
mob->nextMovement = currTime + delay/2 + rand() % (delay/2); mob->nextMovement = currTime + delay/2 + rand() % (delay/2);
// skip move if stunned or asleep
if (mob->appearanceData.iConditionBitFlag & (CSB_BIT_STUN|CSB_BIT_MEZ))
return;
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt); INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
int xStart = mob->spawnX - mob->idleRange/2; int xStart = mob->spawnX - mob->idleRange/2;
int yStart = mob->spawnY - mob->idleRange/2; int yStart = mob->spawnY - mob->idleRange/2;
@ -198,6 +206,13 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
pkt.iToY = mob->appearanceData.iY = yStart + rand() % mob->idleRange; pkt.iToY = mob->appearanceData.iY = yStart + rand() % mob->idleRange;
pkt.iToZ = mob->appearanceData.iZ; pkt.iToZ = mob->appearanceData.iZ;
// roughly halve movement speed if snared
// TODO: this logic isn't quite right yet, since they still get to the same spot
if (mob->appearanceData.iConditionBitFlag & CSB_BIT_DN_MOVE_SPEED) {
mob->nextMovement += delay;
pkt.iSpeed /= 2;
}
auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY); auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY);
auto chunks = ChunkManager::grabChunks(chunk); auto chunks = ChunkManager::grabChunks(chunk);

View File

@ -20,6 +20,7 @@ enum class MobState {
struct Mob : public BaseNPC { struct Mob : public BaseNPC {
MobState state; MobState state;
const int maxHealth; const int maxHealth;
time_t killedTime = 0; time_t killedTime = 0;
const int regenTime; const int regenTime;
bool despawned = false; // for the sake of death animations bool despawned = false; // for the sake of death animations
@ -42,6 +43,8 @@ struct Mob : public BaseNPC {
spawnY = appearanceData.iY; spawnY = appearanceData.iY;
spawnZ = appearanceData.iZ; spawnZ = appearanceData.iZ;
appearanceData.iConditionBitFlag = 0;
// NOTE: there appear to be discrepancies in the dump // NOTE: there appear to be discrepancies in the dump
appearanceData.iHP = maxHealth; appearanceData.iHP = maxHealth;
} }

View File

@ -318,7 +318,7 @@ bool doDebuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage_N_Debuff *re
respdata[i].iDamage = amount; respdata[i].iDamage = amount;
respdata[i].iID = mob->appearanceData.iNPC_ID; respdata[i].iID = mob->appearanceData.iNPC_ID;
respdata[i].iHP = mob->appearanceData.iHP; respdata[i].iHP = mob->appearanceData.iHP;
respdata[i].iConditionBitFlag = iCBFlag; respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag;
std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl;
@ -336,7 +336,7 @@ bool doBuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Buff *respdata, int i
respdata[i].eCT = 4; respdata[i].eCT = 4;
respdata[i].iID = mob->appearanceData.iNPC_ID; respdata[i].iID = mob->appearanceData.iNPC_ID;
respdata[i].iConditionBitFlag = iCBFlag; respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag;
std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl;
@ -382,6 +382,9 @@ bool doDamage(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage *respdata, i
mob->appearanceData.iHP -= amount; mob->appearanceData.iHP -= amount;
// wake up sleeping monster
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
if (mob->appearanceData.iHP <= 0) if (mob->appearanceData.iHP <= 0)
MobManager::killMob(sock, mob); MobManager::killMob(sock, mob);
@ -432,6 +435,9 @@ bool doLeech(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *healdata, i
mob->appearanceData.iHP -= amount; mob->appearanceData.iHP -= amount;
// wake up sleeping monster
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
if (mob->appearanceData.iHP <= 0) if (mob->appearanceData.iHP <= 0)
MobManager::killMob(sock, mob); MobManager::killMob(sock, mob);
@ -506,7 +512,7 @@ std::vector<ActivePower> ActivePowers = {
ActivePower(StunPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_STUN, CSB_BIT_STUN, 0), ActivePower(StunPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_STUN, CSB_BIT_STUN, 0),
ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 333), ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 333),
// TODO: Recall // TODO: Recall
ActivePower(DrainPowers, activePower<sSkillResult_Buff, doBuff>, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 0), ActivePower(DrainPowers, activePower<sSkillResult_Buff, doBuff>, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 0),
ActivePower(SnarePowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 0), ActivePower(SnarePowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 0),
ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 133), ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 133),
// TODO: GroupRevive // TODO: GroupRevive