mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
Implemented GM SpecialState Handling
Co-authored-by: dongresource <dongresource@protonmail.com>
This commit is contained in:
parent
c9be0e5402
commit
efb3df7133
@ -25,6 +25,7 @@ void MobManager::init() {
|
|||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_COMBAT_BEGIN, combatBegin);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_COMBAT_BEGIN, combatBegin);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_COMBAT_END, combatEnd);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_COMBAT_END, combatEnd);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_DOT_DAMAGE_ONOFF, dotDamageOnOff);
|
REGISTER_SHARD_PACKET(P_CL2FE_DOT_DAMAGE_ONOFF, dotDamageOnOff);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ATTACK_CHARs, pcAttackChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
|
void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
|
||||||
@ -212,8 +213,11 @@ void MobManager::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
mob->appearanceData.iConditionBitFlag = 0;
|
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?
|
||||||
|
|
||||||
giveReward(sock);
|
// check for the edge case where hitting the mob did not aggro it
|
||||||
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType);
|
if (sock != nullptr) {
|
||||||
|
giveReward(sock);
|
||||||
|
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType);
|
||||||
|
}
|
||||||
|
|
||||||
mob->despawned = false;
|
mob->despawned = false;
|
||||||
}
|
}
|
||||||
@ -620,3 +624,92 @@ std::pair<int,int> MobManager::getDamage(int attackPower, int defensePower, bool
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) {
|
||||||
|
sP_CL2FE_REQ_PC_ATTACK_CHARs* pkt = (sP_CL2FE_REQ_PC_ATTACK_CHARs*)data->buf;
|
||||||
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
// Unlike the attack mob packet, attacking players packet has an 8-byte trail (Instead of 4 bytes).
|
||||||
|
if (!validInVarPacket(sizeof(sP_CL2FE_REQ_PC_ATTACK_CHARs), pkt->iTargetCnt, sizeof(int32_t) * 2, data->size)) {
|
||||||
|
std::cout << "[WARN] bad sP_CL2FE_REQ_PC_ATTACK_CHARs packet size\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t *pktdata = (int32_t*)((uint8_t*)data->buf + sizeof(sP_CL2FE_REQ_PC_ATTACK_CHARs));
|
||||||
|
|
||||||
|
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC), pkt->iTargetCnt, sizeof(sAttackResult))) {
|
||||||
|
std::cout << "[WARN] bad sP_FE2CL_PC_ATTACK_CHARs_SUCC packet size\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize response struct
|
||||||
|
size_t resplen = sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC) + pkt->iTargetCnt * sizeof(sAttackResult);
|
||||||
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
memset(respbuf, 0, resplen);
|
||||||
|
|
||||||
|
sP_FE2CL_PC_ATTACK_CHARs_SUCC *resp = (sP_FE2CL_PC_ATTACK_CHARs_SUCC*)respbuf;
|
||||||
|
sAttackResult *respdata = (sAttackResult*)(respbuf+sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC));
|
||||||
|
|
||||||
|
resp->iTargetCnt = pkt->iTargetCnt;
|
||||||
|
|
||||||
|
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||||
|
if (pktdata[i*2+1] == 1) { // eCT == 1; attack player
|
||||||
|
Player *target = nullptr;
|
||||||
|
|
||||||
|
for (auto& pair : PlayerManager::players) {
|
||||||
|
if (pair.second.plr->iID == pktdata[i*2]) {
|
||||||
|
target = pair.second.plr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target == nullptr) {
|
||||||
|
// you shall not pass
|
||||||
|
std::cout << "[WARN] pcAttackChars: player ID not found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target->HP -= 100;
|
||||||
|
|
||||||
|
respdata[i].eCT = pktdata[i*2+1];
|
||||||
|
respdata[i].iID = target->iID;
|
||||||
|
respdata[i].iDamage = 100;
|
||||||
|
respdata[i].iHP = target->HP;
|
||||||
|
respdata[i].iHitFlag = 2; // hitscan, not a rocket or a grenade
|
||||||
|
} else { // eCT == 4; attack mob
|
||||||
|
if (Mobs.find(pktdata[i*2]) == Mobs.end()) {
|
||||||
|
// not sure how to best handle this
|
||||||
|
std::cout << "[WARN] pcAttackNpcs: mob ID not found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Mob *mob = Mobs[pktdata[i*2]];
|
||||||
|
|
||||||
|
std::pair<int,int> damage;
|
||||||
|
|
||||||
|
if (pkt->iTargetCnt > 1)
|
||||||
|
damage = getDamage(plr->groupDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]);
|
||||||
|
else
|
||||||
|
damage = getDamage(plr->pointDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]);
|
||||||
|
|
||||||
|
damage.first = hitMob(sock, mob, damage.first);
|
||||||
|
|
||||||
|
respdata[i].eCT = pktdata[i*2+1];
|
||||||
|
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
||||||
|
respdata[i].iDamage = damage.first;
|
||||||
|
respdata[i].iHP = mob->appearanceData.iHP;
|
||||||
|
respdata[i].iHitFlag = damage.second; // hitscan, not a rocket or a grenade
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sock->sendPacket((void*)respbuf, P_FE2CL_PC_ATTACK_CHARs_SUCC, resplen);
|
||||||
|
|
||||||
|
// a bit of a hack: these are the same size, so we can reuse the response packet
|
||||||
|
assert(sizeof(sP_FE2CL_PC_ATTACK_NPCs_SUCC) == sizeof(sP_FE2CL_PC_ATTACK_CHARs));
|
||||||
|
sP_FE2CL_PC_ATTACK_CHARs *resp1 = (sP_FE2CL_PC_ATTACK_CHARs*)respbuf;
|
||||||
|
|
||||||
|
resp1->iPC_ID = plr->iID;
|
||||||
|
|
||||||
|
// send to other players
|
||||||
|
PlayerManager::sendToViewable(sock, (void*)respbuf, P_FE2CL_PC_ATTACK_CHARs, resplen);
|
||||||
|
}
|
||||||
|
@ -105,4 +105,6 @@ namespace MobManager {
|
|||||||
void giveReward(CNSocket *sock);
|
void giveReward(CNSocket *sock);
|
||||||
std::pair<int,int> lerp(int, int, int, int, int);
|
std::pair<int,int> lerp(int, int, int, int, int);
|
||||||
std::pair<int,int> getDamage(int, int, bool, int);
|
std::pair<int,int> getDamage(int, int, bool, int);
|
||||||
|
|
||||||
|
void pcAttackChars(CNSocket *sock, CNPacketData *data);
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ struct Player {
|
|||||||
int32_t iWarpLocationFlag;
|
int32_t iWarpLocationFlag;
|
||||||
int64_t aSkywayLocationFlag[2];
|
int64_t aSkywayLocationFlag[2];
|
||||||
int32_t iConditionBitFlag;
|
int32_t iConditionBitFlag;
|
||||||
|
int8_t iSpecialState;
|
||||||
|
|
||||||
int x, y, z, angle;
|
int x, y, z, angle;
|
||||||
sItemBase Equip[AEQUIP_COUNT];
|
sItemBase Equip[AEQUIP_COUNT];
|
||||||
|
@ -35,6 +35,7 @@ void PlayerManager::init() {
|
|||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_REGEN, PlayerManager::revivePlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_REGEN, PlayerManager::revivePlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, PlayerManager::exitGame);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, PlayerManager::exitGame);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH, PlayerManager::setSpecialSwitchPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH, PlayerManager::setSpecialSwitchPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH, PlayerManager::setGMSpecialSwitchPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_ON, PlayerManager::enterPlayerVehicle);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_ON, PlayerManager::enterPlayerVehicle);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, PlayerManager::exitPlayerVehicle);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VEHICLE_OFF, PlayerManager::exitPlayerVehicle);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_CHANGE_MENTOR, PlayerManager::changePlayerGuide);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_CHANGE_MENTOR, PlayerManager::changePlayerGuide);
|
||||||
@ -152,6 +153,7 @@ void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock
|
|||||||
newPlayer.PCAppearanceData.PCStyle = plr->PCStyle;
|
newPlayer.PCAppearanceData.PCStyle = plr->PCStyle;
|
||||||
newPlayer.PCAppearanceData.Nano = plr->Nanos[plr->activeNano];
|
newPlayer.PCAppearanceData.Nano = plr->Nanos[plr->activeNano];
|
||||||
newPlayer.PCAppearanceData.iPCState = plr->iPCState;
|
newPlayer.PCAppearanceData.iPCState = plr->iPCState;
|
||||||
|
newPlayer.PCAppearanceData.iSpecialState = plr->iSpecialState;
|
||||||
memcpy(newPlayer.PCAppearanceData.ItemEquip, plr->Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
memcpy(newPlayer.PCAppearanceData.ItemEquip, plr->Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
||||||
|
|
||||||
otherSock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
otherSock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
||||||
@ -166,6 +168,7 @@ void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock
|
|||||||
newPlayer.PCAppearanceData.PCStyle = otherPlr->PCStyle;
|
newPlayer.PCAppearanceData.PCStyle = otherPlr->PCStyle;
|
||||||
newPlayer.PCAppearanceData.Nano = otherPlr->Nanos[otherPlr->activeNano];
|
newPlayer.PCAppearanceData.Nano = otherPlr->Nanos[otherPlr->activeNano];
|
||||||
newPlayer.PCAppearanceData.iPCState = otherPlr->iPCState;
|
newPlayer.PCAppearanceData.iPCState = otherPlr->iPCState;
|
||||||
|
newPlayer.PCAppearanceData.iSpecialState = otherPlr->iSpecialState;
|
||||||
memcpy(newPlayer.PCAppearanceData.ItemEquip, otherPlr->Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
memcpy(newPlayer.PCAppearanceData.ItemEquip, otherPlr->Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
||||||
|
|
||||||
sock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
sock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
||||||
@ -811,12 +814,15 @@ void PlayerManager::exitPlayerVehicle(CNSocket* sock, CNPacketData* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
void PlayerManager::setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
sP_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH* specialData = (sP_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH*)data->buf;
|
setSpecialState(sock, data);
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC, response);
|
}
|
||||||
|
|
||||||
response.iPC_ID = specialData->iPC_ID;
|
void PlayerManager::setGMSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
response.iReqSpecialStateFlag = specialData->iSpecialStateFlag;
|
|
||||||
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC, sizeof(sP_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC));
|
if (getPlayer(sock)->accountLevel > 30)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setSpecialState(sock, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
|
void PlayerManager::changePlayerGuide(CNSocket *sock, CNPacketData *data) {
|
||||||
@ -893,4 +899,24 @@ void PlayerManager::exitDuplicate(int accountId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerManager::setSpecialState(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
Player *plr = getPlayer(sock);
|
||||||
|
|
||||||
|
sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH* setData = (sP_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH*)data->buf;
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_SPECIAL_STATE_CHANGE, response);
|
||||||
|
|
||||||
|
plr->iSpecialState ^= setData->iSpecialStateFlag;
|
||||||
|
|
||||||
|
response.iPC_ID = setData->iPC_ID;
|
||||||
|
response.iReqSpecialStateFlag = setData->iSpecialStateFlag;
|
||||||
|
response.iSpecialState = plr->iSpecialState;
|
||||||
|
|
||||||
|
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC, sizeof(sP_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC));
|
||||||
|
sendToViewable(sock, (void*)&response, P_FE2CL_PC_SPECIAL_STATE_CHANGE, sizeof(sP_FE2CL_PC_SPECIAL_STATE_CHANGE));
|
||||||
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -54,6 +54,7 @@ namespace PlayerManager {
|
|||||||
void exitGame(CNSocket* sock, CNPacketData* data);
|
void exitGame(CNSocket* sock, CNPacketData* data);
|
||||||
|
|
||||||
void setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
void setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
|
void setGMSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void changePlayerGuide(CNSocket *sock, CNPacketData *data);
|
void changePlayerGuide(CNSocket *sock, CNPacketData *data);
|
||||||
|
|
||||||
void enterPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
void enterPlayerVehicle(CNSocket* sock, CNPacketData* data);
|
||||||
@ -64,4 +65,5 @@ namespace PlayerManager {
|
|||||||
|
|
||||||
bool isAccountInUse(int accountId);
|
bool isAccountInUse(int accountId);
|
||||||
void exitDuplicate(int accountId);
|
void exitDuplicate(int accountId);
|
||||||
|
void setSpecialState(CNSocket* sock, CNPacketData* data);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user