CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask) { this->type = 0x0E; this->size = 0x1C; WBUFL(data,(0x04)-4) = PEntity->id; WBUFW(data,(0x08)-4) = PEntity->targid; WBUFB(data,(0x0A)-4) = updatemask; switch(type) { case ENTITY_DESPAWN: { WBUFB(data,(0x0A)-4) = 0x20; updatemask = UPDATE_ALL_MOB; } break; case ENTITY_SPAWN: { updatemask = UPDATE_ALL_MOB; if (PEntity->objtype == TYPE_PET) { WBUFB(data,(0x28)-4) = 0x04; } if (PEntity->look.size == MODEL_EQUIPED || PEntity->look.size == MODEL_CHOCOBO) { updatemask = 0x57; } WBUFB(data,(0x0A)-4) = updatemask; } break; } if (updatemask & UPDATE_POS){ WBUFB(data,(0x0B)-4) = PEntity->loc.p.rotation; WBUFF(data,(0x0C)-4) = PEntity->loc.p.x; WBUFF(data,(0x10)-4) = PEntity->loc.p.y; WBUFF(data,(0x14)-4) = PEntity->loc.p.z; WBUFW(data,(0x18)-4) = PEntity->loc.p.moving; WBUFW(data,(0x1A)-4) = PEntity->m_TargID << 1; WBUFB(data,(0x1C)-4) = PEntity->speed; WBUFB(data,(0x1D)-4) = PEntity->speedsub; } if (PEntity->allegiance == ALLEGIANCE_PLAYER && PEntity->status == STATUS_UPDATE) WBUFB(data, (0x20) - 4) = STATUS_NORMAL; else WBUFB(data, (0x20) - 4) = PEntity->status; switch(PEntity->objtype) { case TYPE_NPC: { if (updatemask & UPDATE_HP) { WBUFB(data,(0x1E)-4) = 0x64; WBUFB(data,(0x1F)-4) = PEntity->animation; WBUFB(data,(0x2A)-4) = PEntity->animationsub; WBUFL(data,(0x21)-4) = ((CNpcEntity*)PEntity)->unknown; WBUFB(data,(0x22)-4) |= (PEntity->untargetable ? 0x08 : 0x00); WBUFB(data,(0x22)-4) |= (PEntity->hpvis ? 0x00 : 0x01); WBUFB(data,(0x27)-4) = ((CNpcEntity*)PEntity)->name_prefix; // gender and something else WBUFB(data,(0x29)-4) = PEntity->allegiance; WBUFB(data,(0x2B)-4) = PEntity->namevis; } } break; case TYPE_MOB: { CMobEntity* PMob = (CMobEntity*)PEntity; if(PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC && PMob->PBattleAI->GetCurrentAction() == ACTION_FALL) { WBUFB(data,(0x21)-4) = 0x99; //WBUFB (data,(0x27)-4) = 0x28; WBUFB(data,(0x1E)-4) = 0x00; //0% HP WBUFB(data,(0x1F)-4) = ANIMATION_DEATH; //death anim WBUFB(data,(0x20)-4) = STATUS_NORMAL; WBUFB(data,(0x29)-4) = PEntity->allegiance; WBUFB(data,(0x2B)-4) = PEntity->namevis; } else { if (updatemask & UPDATE_HP) { WBUFB(data,(0x1E)-4) = PMob->GetHPP(); WBUFB(data,(0x1F)-4) = PEntity->animation; WBUFB(data,(0x2A)-4) = PEntity->animationsub; WBUFL(data,(0x21)-4) = PMob->m_unknown; WBUFB(data,(0x21)-4) |= PMob->m_CallForHelp; WBUFB(data,(0x22)-4) |= (PEntity->untargetable ? 0x08 : 0x00); WBUFB(data,(0x22)-4) |= (PEntity->hpvis ? 0x00 : 0x01); WBUFB(data,(0x27)-4) = PMob->m_name_prefix; if (PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC) WBUFB(data,(0x27)-4) |= 0x08; WBUFB(data,(0x28)-4) |= (PMob->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00); WBUFB(data,(0x29)-4) = PEntity->allegiance; WBUFB(data, (0x2B) - 4) = 0;//PEntity->namevis; } if (updatemask & UPDATE_STATUS) { WBUFL(data, (0x2C) - 4) = PMob->m_OwnerID.id; } } if (updatemask & UPDATE_NAME) { //depending on size of name, this can be 0x20, 0x22, or 0x24 this->size = 0x24; memcpy(data + (0x34) - 4, PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size())); } } break; case TYPE_PET: { if(((CPetEntity*)PEntity)->PBattleAI->GetCurrentAction()==ACTION_FALL){ WBUFB(data,(0x21)-4) = 0x99; WBUFB(data,(0x25)-4) = 0x08; WBUFB(data,(0x27)-4) = 0x08 | ((CPetEntity*)PEntity)->m_name_prefix; WBUFB(data,(0x29)-4) = PEntity->allegiance; WBUFB(data,(0x28)-4) = (((CBattleEntity*)PEntity)->health.hp > 0 ? 0x08 : 0x00); WBUFB(data,(0x1E)-4) = 0x00; //0% HP WBUFB(data,(0x1F)-4) = ANIMATION_DEATH; WBUFB(data,(0x20)-4) = STATUS_NORMAL; } else{ if (updatemask & UPDATE_HP) { WBUFB(data,(0x1E)-4) = ((CPetEntity*)PEntity)->GetHPP(); WBUFB(data,(0x1F)-4) = PEntity->animation; WBUFB(data,(0x2A)-4) = PEntity->animationsub; WBUFB(data,(0x28)-4) |= (((CPetEntity*)PEntity)->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00); WBUFB(data,(0x29)-4) = PEntity->allegiance; } if (updatemask & UPDATE_STATUS) { WBUFB(data,(0x27)-4) = 0x08 | ((CPetEntity*)PEntity)->m_name_prefix; } if (updatemask & UPDATE_NAME) { this->size = 0x24; memcpy(data + (0x34) - 4, PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size())); } } } break; } switch(PEntity->look.size) { case MODEL_STANDARD: case MODEL_UNK_5: case MODEL_AUTOMATON: { WBUFL(data,(0x30)-4) = RBUFL(&PEntity->look,0); } break; case MODEL_EQUIPED: case MODEL_CHOCOBO: { this->size = 0x24; memcpy(data + (0x30) - 4, &(PEntity->look), 20); } break; case MODEL_DOOR: case MODEL_ELEVATOR: case MODEL_SHIP: { this->size = 0x24; WBUFW (data,(0x30)-4) = PEntity->look.size; memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 12 ? 12 : PEntity->name.size())); } break; } }
CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type) { this->type = 0x0E; this->size = 0x1C; WBUFL(data,(0x04)-4) = PEntity->id; WBUFW(data,(0x08)-4) = PEntity->targid; switch(type) { case ENTITY_DESPAWN: { switch(PEntity->objtype) { case TYPE_NPC: { WBUFB(data,(0x0A)-4) = 0x20; } break; case TYPE_MOB: { WBUFB(data,(0x0A)-4) = 0x07; WBUFB(data,(0x20)-4) = 0x07; } break; case TYPE_PET: { WBUFB(data,(0x0A)-4) = 0x20; } break; } } break; case ENTITY_SPAWN: { switch(PEntity->objtype) { case TYPE_PET: { WBUFB(data,(0x28)-4) = 0x04; } break; } } case ENTITY_UPDATE: { WBUFB(data,(0x0B)-4) = PEntity->loc.p.rotation; WBUFF(data,(0x0C)-4) = PEntity->loc.p.x; WBUFF(data,(0x10)-4) = PEntity->loc.p.y; WBUFF(data,(0x14)-4) = PEntity->loc.p.z; WBUFW(data,(0x18)-4) = PEntity->loc.p.moving; WBUFW(data,(0x1A)-4) = PEntity->m_TargID << 1; WBUFB(data,(0x1C)-4) = PEntity->speed; WBUFB(data,(0x1D)-4) = PEntity->speedsub; WBUFB(data,(0x1F)-4) = PEntity->animation; WBUFB(data,(0x20)-4) = PEntity->status; WBUFB(data,(0x2A)-4) = PEntity->animationsub; WBUFB(data,(0x2B)-4) = PEntity->namevis; switch(PEntity->objtype) { case TYPE_NPC: { WBUFB(data,(0x1E)-4) = 0x64; WBUFL(data,(0x21)-4) = ((CNpcEntity*)PEntity)->unknown; WBUFB(data,(0x27)-4) = ((CNpcEntity*)PEntity)->name_prefix; // gender and something else } break; case TYPE_MOB: { CMobEntity* PMob = (CMobEntity*)PEntity; if(PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC) { //charmed mob if(PMob->PMaster->objtype = TYPE_PC) { if(PMob->PBattleAI->GetCurrentAction()==ACTION_FALL) { WBUFB(data,(0x0A)-4) = 0x07; WBUFB (data,(0x21)-4) = 0x99; //WBUFB (data,(0x27)-4) = 0x28; WBUFW(data,(0x1A)-4) = 0x00; WBUFW(data,(0x1B)-4) = 0x00; WBUFB (data,(0x1E)-4) = 0x00; //0% HP WBUFB (data,(0x1F)-4) = ANIMATION_DEATH; //death anim WBUFB (data,(0x20)-4) = STATUS_NORMAL; } else { this->size = 0x24; WBUFB (data,(0x1E)-4) = PMob->GetHPP(); WBUFB (data,(0x27)-4) = 0x08; memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 15 ? 15 : PEntity->name.size())); } } } else { WBUFB(data,(0x1E)-4) = PMob->GetHPP(); WBUFL(data,(0x21)-4) = PMob->m_unknown; WBUFB(data,(0x21)-4) |= PMob->m_CallForHelp; WBUFB(data,(0x27)-4) = PMob->m_name_prefix; WBUFL(data,(0x2C)-4) = PMob->m_OwnerID.id; //set bit0 to 1 to make HP bars invisible e.g. Yilgeban, another bit somewhere controls mob targetability //WBUFB(data,(0x22)-4) = 0; if (PMob->PMaster != NULL && PMob->PMaster->objtype == TYPE_PC) WBUFB(data,(0x27)-4) = 0x08; //todo: may need |= } } break; case TYPE_PET: { if(((CPetEntity*)PEntity)->PBattleAI->GetCurrentAction()==ACTION_FALL){ WBUFB(data,(0x0A)-4) = 0x07; WBUFB(data,(0x21)-4) = 0x99; //WBUFB(data,(0x27)-4) = 0x28; WBUFW(data,(0x1A)-4) = 0x00; WBUFB(data,(0x1E)-4) = 0x00; //0% HP WBUFB(data,(0x1F)-4) = ANIMATION_DEATH; WBUFB(data,(0x20)-4) = STATUS_NORMAL; } else{ this->size = 0x24; WBUFB (data,(0x1E)-4) = ((CPetEntity*)PEntity)->GetHPP(); WBUFB (data,(0x27)-4) = 0x08; memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 15 ? 15 : PEntity->name.size())); } } break; } switch(PEntity->look.size) { case MODEL_STANDARD: case MODEL_UNK_5: case MODEL_UNK_6: { WBUFB(data,(0x0A)-4) = 0x0F; WBUFL(data,(0x30)-4) = RBUFL(&PEntity->look,0); } break; case MODEL_EQUIPED: case MODEL_CHOCOBO: { this->size = 0x24; WBUFB (data,(0x0A)-4) = 0x57; memcpy(data+(0x30)-4, &(PEntity->look), 20); } break; case MODEL_DOOR: case MODEL_ELEVATOR: case MODEL_SHIP: { this->size = 0x24; WBUFB (data,(0x0A)-4) = 0x07; WBUFW (data,(0x30)-4) = PEntity->look.size; memcpy(data+(0x34)-4, PEntity->GetName(),(PEntity->name.size() > 12 ? 12 : PEntity->name.size())); } break; } } break; } }
CEntityUpdatePacket::CEntityUpdatePacket(CBaseEntity* PEntity, ENTITYUPDATE type, uint8 updatemask) { this->type = 0x0E; this->size = 0x1C; ref<uint32>(0x04) = PEntity->id; ref<uint16>(0x08) = PEntity->targid; ref<uint8>(0x0A) = updatemask; switch (type) { case ENTITY_DESPAWN: { ref<uint8>(0x0A) = 0x20; updatemask = UPDATE_ALL_MOB; } break; case ENTITY_SPAWN: { updatemask = UPDATE_ALL_MOB; if (PEntity->objtype == TYPE_PET) { ref<uint8>(0x28) = 0x04; } if (PEntity->look.size == MODEL_EQUIPED || PEntity->look.size == MODEL_CHOCOBO) { updatemask = 0x57; } ref<uint8>(0x0A) = updatemask; } break; default: { break; } } if (updatemask & UPDATE_POS) { ref<uint8>(0x0B) = PEntity->loc.p.rotation; ref<float>(0x0C) = PEntity->loc.p.x; ref<float>(0x10) = PEntity->loc.p.y; ref<float>(0x14) = PEntity->loc.p.z; ref<uint16>(0x18) = PEntity->loc.p.moving; ref<uint16>(0x1A) = PEntity->m_TargID << 1; ref<uint8>(0x1C) = PEntity->speed; ref<uint8>(0x1D) = PEntity->speedsub; } if (PEntity->allegiance == ALLEGIANCE_PLAYER && PEntity->status == STATUS_MOB) ref<uint8>(0x20) = STATUS_NORMAL; else ref<uint8>(0x20) = PEntity->status; switch (PEntity->objtype) { case TYPE_NPC: { if (updatemask & UPDATE_HP) { ref<uint8>(0x1E) = 0x64; ref<uint8>(0x1F) = PEntity->animation; ref<uint8>(0x2A) = PEntity->animationsub; ref<uint32>(0x21) = ((CNpcEntity*)PEntity)->m_flags; ref<uint8>(0x27) = ((CNpcEntity*)PEntity)->name_prefix; // gender and something else ref<uint8>(0x29) = PEntity->allegiance; ref<uint8>(0x2B) = PEntity->namevis; } } break; case TYPE_MOB: case TYPE_PET: { CMobEntity* PMob = (CMobEntity*)PEntity; //if(PMob->PMaster != nullptr && PMob->PMaster->objtype == TYPE_PC && // PMob->PBattleAI->GetCurrentAction() == ACTION_FALL) //{ // ref<uint8>(data,(0x21)) = 0x99; // //ref<uint8> (data,(0x27)) = 0x28; // ref<uint8>(data,(0x1E)) = 0x00; //0% HP // ref<uint8>(data,(0x1F)) = ANIMATION_DEATH; //death anim // ref<uint8>(data,(0x20)) = STATUS_NORMAL; // ref<uint8>(data,(0x29)) = PEntity->allegiance; // ref<uint8>(data,(0x2B)) = PEntity->namevis; //} //else { if (updatemask & UPDATE_HP) { ref<uint8>(0x1E) = PMob->GetHPP(); ref<uint8>(0x1F) = PEntity->animation; ref<uint8>(0x2A) = PEntity->animationsub; ref<uint32>(0x21) = PMob->m_flags; ref<uint8>(0x25) = PMob->health.hp > 0 ? 0x08 : 0; ref<uint8>(0x27) = PMob->m_name_prefix; if (PMob->PMaster != nullptr && PMob->PMaster->objtype == TYPE_PC) ref<uint8>(0x27) |= 0x08; ref<uint8>(0x28) |= (PMob->StatusEffectContainer->HasStatusEffect(EFFECT_TERROR) ? 0x10 : 0x00); ref<uint8>(0x28) |= PMob->health.hp > 0 && PMob->animation == ANIMATION_DEATH ? 0x08 : 0; ref<uint8>(0x29) = PEntity->allegiance; ref<uint8>(0x2B) = PEntity->namevis; } if (updatemask & UPDATE_STATUS) { ref<uint32>(0x2C) = PMob->m_OwnerID.id; } } if (updatemask & UPDATE_NAME) { //depending on size of name, this can be 0x20, 0x22, or 0x24 this->size = 0x24; if (PMob->packetName.empty()) memcpy(data + (0x34), PEntity->GetName(), (PEntity->name.size() > 15 ? 15 : PEntity->name.size())); else memcpy(data + (0x34), PMob->packetName.c_str(), (PMob->packetName.size() > 15 ? 15 : PMob->packetName.size())); } } break; default: { break; } } switch (PEntity->look.size) { case MODEL_STANDARD: case MODEL_UNK_5: case MODEL_AUTOMATON: { ref<uint32>(0x30) = ::ref<uint32>(&PEntity->look, 0); } break; case MODEL_EQUIPED: case MODEL_CHOCOBO: { this->size = 0x24; memcpy(data + (0x30), &(PEntity->look), 20); } break; case MODEL_DOOR: case MODEL_ELEVATOR: case MODEL_SHIP: { this->size = 0x24; ref<uint16>(0x30) = PEntity->look.size; memcpy(data + (0x34), PEntity->GetName(), (PEntity->name.size() > 12 ? 12 : PEntity->name.size())); } break; } }
void DespawnPet(CBattleEntity* PMaster) { DSP_DEBUG_BREAK_IF(PMaster->PPet == NULL); CBattleEntity* PPet = PMaster->PPet; // mob was not reset properly on death/uncharm // reset manually if (PPet->isCharmed && PMaster->objtype == TYPE_MOB) { PPet->isCharmed = false; PMaster->charmTime = 0; delete PPet->PBattleAI; PPet->PBattleAI = new CAIMobDummy((CMobEntity*)PMaster); PPet->PBattleAI->SetLastActionTime(gettick()); PPet->PBattleAI->SetCurrentAction(ACTION_FALL); ShowDebug("An ex charmed mob was not reset properly, Manually resetting it.\n"); return; } switch (PPet->objtype) { case TYPE_PET: { PPet->PBattleAI->SetCurrentAction(ACTION_FALL); if( ((CPetEntity*)PPet)->getPetType() == PETTYPE_AVATAR ) PMaster->setModifier(MOD_AVATAR_PERPETUATION, 0); if (PMaster->PParty != NULL) { for (uint8 i = 0; i < PMaster->PParty->members.size(); ++i) { CCharEntity* PMember = (CCharEntity*)PMaster->PParty->members.at(i); PMember->PLatentEffectContainer->CheckLatentsPartyAvatar(); } } CCharEntity* PChar = (CCharEntity*)PMaster; PChar->PLatentEffectContainer->CheckLatentsPartyAvatar(); } break; case TYPE_MOB: { if(PMaster->objtype == TYPE_PC) { CMobEntity* PMob = (CMobEntity*)PMaster->PPet; CCharEntity* PChar = (CCharEntity*)PMaster; // mobs charm wears off whist fighting another mob. Both mobs now attack player since mobs are no longer enemies if(PMob->PBattleAI != NULL && PMob->PBattleAI->GetBattleTarget() != NULL && PMob->PBattleAI->GetBattleTarget()->objtype == TYPE_MOB){ ((CMobEntity*)PMob->PBattleAI->GetBattleTarget())->PEnmityContainer->Clear(); ((CMobEntity*)PMob->PBattleAI->GetBattleTarget())->PEnmityContainer->UpdateEnmity(PChar, 0, 0); } //clear the ex-charmed mobs enmity PMob->PEnmityContainer->Clear(); // charm time is up, mob attacks player now if (PMob->GetHPP() != 0 && PMob->PMaster->GetHPP() != 0 && distance(PMob->loc.p, PMob->PMaster->loc.p) < 30) { PMob->PEnmityContainer->UpdateEnmity(PChar, 0, 0); } else { PMob->m_OwnerID.clean(); } // dirty exp if not full PMob->m_giveExp = PMob->GetHPP() == 100; //master using leave command if (PMaster->PBattleAI->GetCurrentAction() == ACTION_JOBABILITY_FINISH && PMaster->PBattleAI->GetCurrentJobAbility()->getID() == 55 || PChar->loc.zoning) { PMob->PEnmityContainer->Clear(); PMob->m_OwnerID.clean(); } PMob->isCharmed = false; PMob->charmTime = 0; PMob->PMaster = NULL; delete PMob->PBattleAI; PMob->PBattleAI = new CAIMobDummy(PMob); PMob->PBattleAI->SetLastActionTime(gettick()); if (PMob->GetHPP() == 0) PMob->PBattleAI->SetCurrentAction(ACTION_FALL); else PMob->PBattleAI->SetCurrentAction(ACTION_DISENGAGE); PChar->PPet = NULL; PChar->pushPacket(new CCharUpdatePacket(PChar)); PMob->loc.zone->PushPacket(PMob, CHAR_INRANGE, new CEntityUpdatePacket(PMob, ENTITY_UPDATE)); } } break; case TYPE_PC: { // освобождаем персонажа из под контроля } break; } }