Compare commits

..

2 Commits

Author SHA1 Message Date
gsemaj
9394825d41
Fix recall 2023-07-12 17:43:05 -04:00
gsemaj
6e0d55c4b7
Make SkillType an enum class 2023-07-12 17:37:05 -04:00
6 changed files with 116 additions and 96 deletions

View File

@ -97,8 +97,13 @@ static SkillResult handleSkillBatteryDrain(SkillData* skill, int power, ICombata
static SkillResult handleSkillMove(SkillData* skill, int power, ICombatant* source, ICombatant* target) { static SkillResult handleSkillMove(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
if(source->getCharType() != 1) if(source->getCharType() != 1)
return SkillResult(); // only Players are valid sources for recall return SkillResult(); // only Players are valid sources for recall
Player* plr = dynamic_cast<Player*>(source); Player* plr = dynamic_cast<Player*>(source);
PlayerManager::sendPlayerTo(source->getRef().sock, plr->recallX, plr->recallY, plr->recallZ, plr->recallInstance); if(source == target) {
// no trailing struct for self
PlayerManager::sendPlayerTo(target->getRef().sock, plr->recallX, plr->recallY, plr->recallZ, plr->recallInstance);
return SkillResult();
}
sSkillResult_Move result{}; sSkillResult_Move result{};
result.eCT = target->getCharType(); result.eCT = target->getCharType();
@ -126,50 +131,50 @@ static std::vector<SkillResult> handleSkill(SkillData* skill, int power, ICombat
switch(skill->skillType) switch(skill->skillType)
{ {
case EST_DAMAGE: case SkillType::DAMAGE:
resultSize = sizeof(sSkillResult_Damage); resultSize = sizeof(sSkillResult_Damage);
skillHandler = handleSkillDamage; skillHandler = handleSkillDamage;
break; break;
case EST_HEAL_HP: case SkillType::HEAL_HP:
case EST_RETURNHOMEHEAL: case SkillType::RETURNHOMEHEAL:
resultSize = sizeof(sSkillResult_Heal_HP); resultSize = sizeof(sSkillResult_Heal_HP);
skillHandler = handleSkillHealHP; skillHandler = handleSkillHealHP;
break; break;
case EST_JUMP: case SkillType::JUMP:
case EST_RUN: case SkillType::RUN:
case EST_FREEDOM: case SkillType::FREEDOM:
case EST_PHOENIX: case SkillType::PHOENIX:
case EST_INVULNERABLE: case SkillType::INVULNERABLE:
case EST_MINIMAPENEMY: case SkillType::MINIMAPENEMY:
case EST_MINIMAPTRESURE: case SkillType::MINIMAPTRESURE:
case EST_NANOSTIMPAK: case SkillType::NANOSTIMPAK:
case EST_PROTECTBATTERY: case SkillType::PROTECTBATTERY:
case EST_PROTECTINFECTION: case SkillType::PROTECTINFECTION:
case EST_REWARDBLOB: case SkillType::REWARDBLOB:
case EST_REWARDCASH: case SkillType::REWARDCASH:
case EST_STAMINA_SELF: case SkillType::STAMINA_SELF:
case EST_STEALTH: case SkillType::STEALTH:
resultSize = sizeof(sSkillResult_Buff); resultSize = sizeof(sSkillResult_Buff);
skillHandler = handleSkillBuff; skillHandler = handleSkillBuff;
break; break;
case EST_BATTERYDRAIN: case SkillType::BATTERYDRAIN:
resultSize = sizeof(sSkillResult_BatteryDrain); resultSize = sizeof(sSkillResult_BatteryDrain);
skillHandler = handleSkillBatteryDrain; skillHandler = handleSkillBatteryDrain;
break; break;
case EST_RECALL: // still soft lock case SkillType::RECALL: // still soft lock
case EST_RECALL_GROUP: // works for player who uses it case SkillType::RECALL_GROUP: // works for player who uses it
resultSize = sizeof(sSkillResult_Move); resultSize = sizeof(sSkillResult_Move);
skillHandler = handleSkillMove; skillHandler = handleSkillMove;
break; break;
case EST_PHOENIX_GROUP: // broken case SkillType::PHOENIX_GROUP: // broken
resultSize = sizeof(sSkillResult_Resurrect); resultSize = sizeof(sSkillResult_Resurrect);
skillHandler = handleSkillResurrect; skillHandler = handleSkillResurrect;
break; break;
case EST_RETROROCKET_SELF: case SkillType::RETROROCKET_SELF:
// no-op // no-op
return results; return results;
default: default:
std::cout << "[WARN] Unhandled skill type " << skill->skillType << std::endl; std::cout << "[WARN] Unhandled skill type " << (int)skill->skillType << std::endl;
return results; return results;
} }
@ -178,7 +183,7 @@ static std::vector<SkillResult> handleSkill(SkillData* skill, int power, ICombat
SkillResult result = skillHandler(skill, power, src != nullptr ? src : target, target); SkillResult result = skillHandler(skill, power, src != nullptr ? src : target, target);
if(result.size == 0) continue; // skill not applicable if(result.size == 0) continue; // skill not applicable
if(result.size != resultSize) { if(result.size != resultSize) {
std::cout << "[WARN] bad skill result size for " << skill->skillType << " from " << (void*)handleSkillBuff << std::endl; std::cout << "[WARN] bad skill result size for " << (int)skill->skillType << " from " << (void*)handleSkillBuff << std::endl;
continue; continue;
} }
results.push_back(result); results.push_back(result);
@ -225,12 +230,17 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std:
pkt->iSkillID = nano.iSkillID; pkt->iSkillID = nano.iSkillID;
pkt->iNanoStamina = nano.iStamina; pkt->iNanoStamina = nano.iStamina;
pkt->bNanoDeactive = nano.iStamina <= 0; pkt->bNanoDeactive = nano.iStamina <= 0;
pkt->eST = skill->skillType; pkt->eST = (int32_t)skill->skillType;
pkt->iTargetCnt = (int32_t)results.size(); pkt->iTargetCnt = (int32_t)results.size();
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1)); attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen); sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
if(skill->skillType == SkillType::RECALL_GROUP)
// group recall packet is sent only to group members
PlayerManager::sendToGroup(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
else
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
if (nano.iStamina <= 0) if (nano.iStamina <= 0)
Nanos::summonNano(sock, -1); Nanos::summonNano(sock, -1);
@ -263,7 +273,7 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*>
sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf;
pkt->iNPC_ID = npc.id; pkt->iNPC_ID = npc.id;
pkt->iSkillID = skillID; pkt->iSkillID = skillID;
pkt->eST = skill->skillType; pkt->eST = (int32_t)skill->skillType;
pkt->iTargetCnt = (int32_t)results.size(); pkt->iTargetCnt = (int32_t)results.size();
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1)); attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
@ -283,9 +293,6 @@ static std::vector<ICombatant*> entityRefsToCombatants(std::vector<EntityRef> re
std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* skill, int count, int32_t *ids) { std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* skill, int count, int32_t *ids) {
if(skill->effectTarget == SkillEffectTarget::SELF)
return {src}; // client sends 0 targets for certain self-targeting skills (recall)
if(skill->targetType == SkillTargetType::GROUP) { if(skill->targetType == SkillTargetType::GROUP) {
// group // group
if(count != 1 || ids[0] != src->getID()) { if(count != 1 || ids[0] != src->getID()) {
@ -295,6 +302,10 @@ std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* ski
return entityRefsToCombatants(src->getGroupMembers()); return entityRefsToCombatants(src->getGroupMembers());
} }
// this check *has* to happen after the group check above due to cases like group recall that use both
if(skill->effectTarget == SkillEffectTarget::SELF)
return {src}; // client sends 0 targets for certain self-targeting skills (recall)
// individuals // individuals
std::vector<ICombatant*> targets; std::vector<ICombatant*> targets;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -324,62 +335,62 @@ std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* ski
} }
/* ripped from client (enums emplaced) */ /* ripped from client (enums emplaced) */
int Abilities::getCSTBFromST(int eSkillType) { int Abilities::getCSTBFromST(SkillType skillType) {
int result = 0; int result = 0;
switch (eSkillType) switch (skillType)
{ {
case EST_RUN: case SkillType::RUN:
result = ECSB_UP_MOVE_SPEED; result = ECSB_UP_MOVE_SPEED;
break; break;
case EST_JUMP: case SkillType::JUMP:
result = ECSB_UP_JUMP_HEIGHT; result = ECSB_UP_JUMP_HEIGHT;
break; break;
case EST_STEALTH: case SkillType::STEALTH:
result = ECSB_UP_STEALTH; result = ECSB_UP_STEALTH;
break; break;
case EST_PHOENIX: case SkillType::PHOENIX:
result = ECSB_PHOENIX; result = ECSB_PHOENIX;
break; break;
case EST_PROTECTBATTERY: case SkillType::PROTECTBATTERY:
result = ECSB_PROTECT_BATTERY; result = ECSB_PROTECT_BATTERY;
break; break;
case EST_PROTECTINFECTION: case SkillType::PROTECTINFECTION:
result = ECSB_PROTECT_INFECTION; result = ECSB_PROTECT_INFECTION;
break; break;
case EST_SNARE: case SkillType::SNARE:
result = ECSB_DN_MOVE_SPEED; result = ECSB_DN_MOVE_SPEED;
break; break;
case EST_SLEEP: case SkillType::SLEEP:
result = ECSB_MEZ; result = ECSB_MEZ;
break; break;
case EST_MINIMAPENEMY: case SkillType::MINIMAPENEMY:
result = ECSB_MINIMAP_ENEMY; result = ECSB_MINIMAP_ENEMY;
break; break;
case EST_MINIMAPTRESURE: case SkillType::MINIMAPTRESURE:
result = ECSB_MINIMAP_TRESURE; result = ECSB_MINIMAP_TRESURE;
break; break;
case EST_REWARDBLOB: case SkillType::REWARDBLOB:
result = ECSB_REWARD_BLOB; result = ECSB_REWARD_BLOB;
break; break;
case EST_REWARDCASH: case SkillType::REWARDCASH:
result = ECSB_REWARD_CASH; result = ECSB_REWARD_CASH;
break; break;
case EST_INFECTIONDAMAGE: case SkillType::INFECTIONDAMAGE:
result = ECSB_INFECTION; result = ECSB_INFECTION;
break; break;
case EST_FREEDOM: case SkillType::FREEDOM:
result = ECSB_FREEDOM; result = ECSB_FREEDOM;
break; break;
case EST_BOUNDINGBALL: case SkillType::BOUNDINGBALL:
result = ECSB_BOUNDINGBALL; result = ECSB_BOUNDINGBALL;
break; break;
case EST_INVULNERABLE: case SkillType::INVULNERABLE:
result = ECSB_INVULNERABLE; result = ECSB_INVULNERABLE;
break; break;
case EST_BUFFHEAL: case SkillType::BUFFHEAL:
result = ECSB_HEAL; result = ECSB_HEAL;
break; break;
case EST_NANOSTIMPAK: case SkillType::NANOSTIMPAK:
result = ECSB_STIMPAKSLOT1; result = ECSB_STIMPAKSLOT1;
break; break;
} }

View File

@ -10,6 +10,47 @@
constexpr size_t MAX_SKILLRESULT_SIZE = sizeof(sSkillResult_BatteryDrain); constexpr size_t MAX_SKILLRESULT_SIZE = sizeof(sSkillResult_BatteryDrain);
enum class SkillType {
DAMAGE = 1,
HEAL_HP = 2,
KNOCKDOWN = 3,
SLEEP = 4,
SNARE = 5,
HEAL_STAMINA = 6,
STAMINA_SELF = 7,
STUN = 8,
WEAPONSLOW = 9,
JUMP = 10,
RUN = 11,
STEALTH = 12,
SWIM = 13,
MINIMAPENEMY = 14,
MINIMAPTRESURE = 15,
PHOENIX = 16,
PROTECTBATTERY = 17,
PROTECTINFECTION = 18,
REWARDBLOB = 19,
REWARDCASH = 20,
BATTERYDRAIN = 21,
CORRUPTIONATTACK = 22,
INFECTIONDAMAGE = 23,
KNOCKBACK = 24,
FREEDOM = 25,
PHOENIX_GROUP = 26,
RECALL = 27,
RECALL_GROUP = 28,
RETROROCKET_SELF = 29,
BLOODSUCKING = 30,
BOUNDINGBALL = 31,
INVULNERABLE = 32,
NANOSTIMPAK = 33,
RETURNHOMEHEAL = 34,
BUFFHEAL = 35,
EXTRABANK = 36,
CORRUPTIONATTACKWIN = 38,
CORRUPTIONATTACKLOSE = 39,
};
enum class SkillEffectTarget { enum class SkillEffectTarget {
POINT = 1, POINT = 1,
SELF = 2, SELF = 2,
@ -43,7 +84,7 @@ struct SkillResult {
}; };
struct SkillData { struct SkillData {
int skillType; // eST SkillType skillType; // eST
SkillEffectTarget effectTarget; SkillEffectTarget effectTarget;
int effectType; // always 1? int effectType; // always 1?
SkillTargetType targetType; SkillTargetType targetType;
@ -64,5 +105,5 @@ namespace Abilities {
void useNPCSkill(EntityRef, int skillID, std::vector<ICombatant*>); void useNPCSkill(EntityRef, int skillID, std::vector<ICombatant*>);
std::vector<ICombatant*> matchTargets(ICombatant*, SkillData*, int, int32_t*); std::vector<ICombatant*> matchTargets(ICombatant*, SkillData*, int, int32_t*);
int getCSTBFromST(int eSkillType); int getCSTBFromST(SkillType skillType);
} }

View File

@ -482,7 +482,7 @@ static void itemUseHandler(CNSocket* sock, CNPacketData* data) {
resp->iSlotNum = request->iSlotNum; resp->iSlotNum = request->iSlotNum;
resp->RemainItem = gumball; resp->RemainItem = gumball;
resp->iTargetCnt = 1; resp->iTargetCnt = 1;
resp->eST = EST_NANOSTIMPAK; resp->eST = (int32_t)SkillType::NANOSTIMPAK;
resp->iSkillID = 144; resp->iSkillID = 144;
int eCSB = ECSB_STIMPAKSLOT1 + request->iNanoSlot; int eCSB = ECSB_STIMPAKSLOT1 + request->iNanoSlot;

View File

@ -338,6 +338,14 @@ static void enterPlayer(CNSocket* sock, CNPacketData* data) {
delete lm; delete lm;
} }
void PlayerManager::sendToGroup(CNSocket* sock, void* buf, uint32_t type, size_t size) {
Player* plr = getPlayer(sock);
if (plr->group == nullptr)
return;
for(const EntityRef& ref : plr->group->filter(EntityKind::PLAYER))
ref.sock->sendPacket(buf, type, size);
}
void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) { void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) {
Player* plr = getPlayer(sock); Player* plr = getPlayer(sock);
for (auto it = plr->viewableChunks.begin(); it != plr->viewableChunks.end(); it++) { for (auto it = plr->viewableChunks.begin(); it != plr->viewableChunks.end(); it++) {

View File

@ -33,6 +33,7 @@ namespace PlayerManager {
CNSocket *getSockFromAny(int by, int id, int uid, std::string firstname, std::string lastname); CNSocket *getSockFromAny(int by, int id, int uid, std::string firstname, std::string lastname);
WarpLocation *getRespawnPoint(Player *plr); WarpLocation *getRespawnPoint(Player *plr);
void sendToGroup(CNSocket *sock, void* buf, uint32_t type, size_t size);
void sendToViewable(CNSocket *sock, void* buf, uint32_t type, size_t size); void sendToViewable(CNSocket *sock, void* buf, uint32_t type, size_t size);
// TODO: unify this under the new Entity system // TODO: unify this under the new Entity system

View File

@ -46,49 +46,8 @@ enum class ePCRegenType {
End End
}; };
// nano powers // nano power flags
enum { enum {
EST_NONE = 0,
EST_DAMAGE = 1,
EST_HEAL_HP = 2,
EST_KNOCKDOWN = 3,
EST_SLEEP = 4,
EST_SNARE = 5,
EST_HEAL_STAMINA = 6,
EST_STAMINA_SELF = 7,
EST_STUN = 8,
EST_WEAPONSLOW = 9,
EST_JUMP = 10,
EST_RUN = 11,
EST_STEALTH = 12,
EST_SWIM = 13,
EST_MINIMAPENEMY = 14,
EST_MINIMAPTRESURE = 15,
EST_PHOENIX = 16,
EST_PROTECTBATTERY = 17,
EST_PROTECTINFECTION = 18,
EST_REWARDBLOB = 19,
EST_REWARDCASH = 20,
EST_BATTERYDRAIN = 21,
EST_CORRUPTIONATTACK = 22,
EST_INFECTIONDAMAGE = 23,
EST_KNOCKBACK = 24,
EST_FREEDOM = 25,
EST_PHOENIX_GROUP = 26,
EST_RECALL = 27,
EST_RECALL_GROUP = 28,
EST_RETROROCKET_SELF = 29,
EST_BLOODSUCKING = 30,
EST_BOUNDINGBALL = 31,
EST_INVULNERABLE = 32,
EST_NANOSTIMPAK = 33,
EST_RETURNHOMEHEAL = 34,
EST_BUFFHEAL = 35,
EST_EXTRABANK = 36,
EST__END = 37,
EST_CORRUPTIONATTACKWIN = 38,
EST_CORRUPTIONATTACKLOSE = 39,
ECSB_NONE = 0, ECSB_NONE = 0,
ECSB_UP_MOVE_SPEED = 1, ECSB_UP_MOVE_SPEED = 1,
ECSB_UP_SWIM_SPEED = 2, ECSB_UP_SWIM_SPEED = 2,