mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-12-23 11:50:04 +00:00
UnsummonW Implementation + Tweaks
* UnsummonW can be used to remove the mob from existence. * Mob groups now aggro together. * Mobs space a little bit when chasing the player. * Combat balance tweaked a bit, you can take out an entire boss group of scoria cephalopod with good nano usage with common tier weapons.
This commit is contained in:
parent
5e8b6eec6e
commit
f1d04cec01
@ -284,6 +284,22 @@ void unsummonWCommand(std::string full, std::vector<std::string>& args, CNSocket
|
||||
return;
|
||||
}
|
||||
|
||||
int leadId = ((Mob*)npc)->groupLeader;
|
||||
if (leadId != 0) {
|
||||
Mob* leadNpc = MobManager::Mobs[leadId];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (leadNpc->groupMember[i] == 0)
|
||||
break;
|
||||
|
||||
TableData::RunningMobs.erase(leadNpc->groupMember[i]);
|
||||
NPCManager::destroyNPC(leadNpc->groupMember[i]);
|
||||
}
|
||||
TableData::RunningMobs.erase(leadId);
|
||||
NPCManager::destroyNPC(leadId);
|
||||
ChatManager::sendServerMessage(sock, "/unsummonW: Mob group destroyed.");
|
||||
return;
|
||||
}
|
||||
|
||||
ChatManager::sendServerMessage(sock, "/unsummonW: removed mob with type: " + std::to_string(npc->appearanceData.iNPCType) +
|
||||
", id: " + std::to_string(npc->appearanceData.iNPC_ID));
|
||||
|
||||
@ -509,11 +525,11 @@ void notifyCommand(std::string full, std::vector<std::string>& args, CNSocket* s
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
if (plr->notify) {
|
||||
plr->notify = false;
|
||||
ChatManager::sendServerMessage(sock, "[ADMIN] No longer receiving join notifications");
|
||||
plr->notify = false;
|
||||
ChatManager::sendServerMessage(sock, "[ADMIN] No longer receiving join notifications");
|
||||
} else {
|
||||
plr->notify = true;
|
||||
ChatManager::sendServerMessage(sock, "[ADMIN] Receiving join notifications");
|
||||
plr->notify = true;
|
||||
ChatManager::sendServerMessage(sock, "[ADMIN] Receiving join notifications");
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,14 +539,16 @@ void playersCommand(std::string full, std::vector<std::string>& args, CNSocket*
|
||||
ChatManager::sendServerMessage(sock, PlayerManager::getPlayerName(pair.second));
|
||||
}
|
||||
|
||||
void summonGroupWCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {
|
||||
void summonGroupCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {
|
||||
if (args.size() < 4) {
|
||||
ChatManager::sendServerMessage(sock, "/summonGroupW <leadermob> <mob> <number> [distance]");
|
||||
ChatManager::sendServerMessage(sock, "/summonGroup(W) <leadermob> <mob> <number> [distance]");
|
||||
return;
|
||||
}
|
||||
Player* plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
char *rest;
|
||||
|
||||
bool wCommand = (args[0] == "/summonGroupW");
|
||||
int type = std::strtol(args[1].c_str(), &rest, 10);
|
||||
int type2 = std::strtol(args[2].c_str(), &rest, 10);
|
||||
int count = std::strtol(args[3].c_str(), &rest, 10);
|
||||
@ -586,7 +604,8 @@ void summonGroupWCommand(std::string full, std::vector<std::string>& args, CNSoc
|
||||
}
|
||||
|
||||
// re-enable respawning
|
||||
((Mob*)npc)->summoned = false;
|
||||
if (wCommand)
|
||||
((Mob*)npc)->summoned = false;
|
||||
} else {
|
||||
npc = new BaseNPC(x, y, z + EXTRA_HEIGHT, 0, plr->instanceID, type, id);
|
||||
}
|
||||
@ -612,8 +631,8 @@ void summonGroupWCommand(std::string full, std::vector<std::string>& args, CNSoc
|
||||
mob->offsetX = x - plr->x;
|
||||
mob->offsetY = y - plr->y;
|
||||
}
|
||||
|
||||
((Mob*)npc)->summoned = false;
|
||||
if (wCommand)
|
||||
((Mob*)npc)->summoned = false;
|
||||
} else {
|
||||
npc = new BaseNPC(x, y, z + EXTRA_HEIGHT, 0, MAPNUM(plr->instanceID), type, id);
|
||||
}
|
||||
@ -624,9 +643,10 @@ void summonGroupWCommand(std::string full, std::vector<std::string>& args, CNSoc
|
||||
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, x, y, z);
|
||||
}
|
||||
|
||||
ChatManager::sendServerMessage(sock, "/summonGroupW: placed mob with type: " + std::to_string(type) +
|
||||
ChatManager::sendServerMessage(sock, "/summonGroup(W): placed mob with type: " + std::to_string(type) +
|
||||
", id: " + std::to_string(npc->appearanceData.iNPC_ID));
|
||||
TableData::RunningMobs[npc->appearanceData.iNPC_ID] = npc; // only record the one in the template
|
||||
if (wCommand)
|
||||
TableData::RunningMobs[npc->appearanceData.iNPC_ID] = npc; // only record the one in the template
|
||||
|
||||
if (i == 0 && team == 2) {
|
||||
type = type2;
|
||||
@ -666,7 +686,8 @@ void ChatManager::init() {
|
||||
registerCommand("tasks", 30, tasksCommand, "list all active missions and their respective task ids.");
|
||||
registerCommand("notify", 30, notifyCommand, "receive a message whenever a player joins the server");
|
||||
registerCommand("players", 30, playersCommand, "print all players on the server");
|
||||
registerCommand("summonGroupW", 30, summonGroupWCommand, "permanently summon group NPCs");
|
||||
registerCommand("summonGroup", 30, summonGroupCommand, "summon group NPCs");
|
||||
registerCommand("summonGroupW", 30, summonGroupCommand, "permanently summon group NPCs");
|
||||
}
|
||||
|
||||
void ChatManager::registerCommand(std::string cmd, int requiredLevel, CommandHandler handlr, std::string help) {
|
||||
|
@ -133,7 +133,7 @@ void MobManager::npcAttackPc(Mob *mob, time_t currTime) {
|
||||
sP_FE2CL_NPC_ATTACK_PCs *pkt = (sP_FE2CL_NPC_ATTACK_PCs*)respbuf;
|
||||
sAttackResult *atk = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_NPC_ATTACK_PCs));
|
||||
|
||||
auto damage = getDamage(450 + (int)mob->data["m_iPower"], plr->defense, false, false, -1, -1, rand() % plr->level + 1);
|
||||
auto damage = getDamage(450 + (int)mob->data["m_iPower"], plr->defense, false, false, -1, -1, 0);
|
||||
plr->HP -= damage.first;
|
||||
|
||||
pkt->iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||
@ -338,6 +338,9 @@ int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) {
|
||||
mob->roamX = mob->appearanceData.iX;
|
||||
mob->roamY = mob->appearanceData.iY;
|
||||
mob->roamZ = mob->appearanceData.iZ;
|
||||
|
||||
if (mob->groupLeader != 0)
|
||||
followToCombat(mob);
|
||||
}
|
||||
|
||||
mob->appearanceData.iHP -= damage;
|
||||
@ -560,7 +563,14 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
||||
if (mob->appearanceData.iConditionBitFlag & CSB_BIT_DN_MOVE_SPEED)
|
||||
speed /= 2;
|
||||
|
||||
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->target->plr->x, mob->target->plr->y,std::min(distance-(int)mob->data["m_iAtkRange"]+1, speed*2/5));
|
||||
int targetX = mob->target->plr->x;
|
||||
int targetY = mob->target->plr->y;
|
||||
if (mob->groupLeader != 0) {
|
||||
targetX += mob->offsetX*distance/(mob->sightRange+1);
|
||||
targetY += mob->offsetY*distance/(mob->sightRange+1);
|
||||
}
|
||||
|
||||
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, targetX, targetY, std::min(distance-(int)mob->data["m_iAtkRange"]+1, speed*2/5));
|
||||
|
||||
NPCManager::updateNPCPosition(mob->appearanceData.iNPC_ID, targ.first, targ.second, mob->appearanceData.iZ, mob->instanceID, mob->appearanceData.iAngle);
|
||||
|
||||
@ -570,10 +580,6 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
||||
pkt.iSpeed = speed;
|
||||
pkt.iToX = mob->appearanceData.iX = targ.first;
|
||||
pkt.iToY = mob->appearanceData.iY = targ.second;
|
||||
if (mob->groupLeader != 0 && mob->groupLeader != mob->appearanceData.iNPC_ID) {
|
||||
pkt.iToX += mob->offsetX;
|
||||
pkt.iToY += mob->offsetY;
|
||||
}
|
||||
pkt.iToZ = mob->target->plr->z;
|
||||
pkt.iMoveStyle = 1;
|
||||
|
||||
@ -972,7 +978,7 @@ std::pair<int,int> MobManager::getDamage(int attackPower, int defensePower, bool
|
||||
|
||||
// base calculation
|
||||
int damage = attackPower * attackPower / (attackPower + defensePower);
|
||||
//damage = std::max(10 + attackPower / 10, damage - defensePower * (4 + difficulty) / 100);
|
||||
damage = std::max(10 + attackPower / 10, damage - (defensePower - attackPower / 2) * difficulty / 72);
|
||||
damage = damage * (rand() % 40 + 80) / 100;
|
||||
|
||||
// Adaptium/Blastons/Cosmix
|
||||
@ -1053,7 +1059,7 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) {
|
||||
else
|
||||
damage.first = plr->pointDamage;
|
||||
|
||||
damage = getDamage(damage.first, target->defense, true, (plr->batteryW > 6 + plr->level), -1, -1, 1);
|
||||
damage = getDamage(damage.first, target->defense, true, (plr->batteryW > 6 + plr->level), -1, -1, 0);
|
||||
|
||||
if (plr->batteryW >= 6 + plr->level)
|
||||
plr->batteryW -= 6 + plr->level;
|
||||
@ -1188,6 +1194,9 @@ bool MobManager::aggroCheck(Mob *mob, time_t currTime) {
|
||||
mob->roamY = mob->appearanceData.iY;
|
||||
mob->roamZ = mob->appearanceData.iZ;
|
||||
|
||||
if (mob->groupLeader != 0)
|
||||
followToCombat(mob);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1380,3 +1389,39 @@ void MobManager::projectileHit(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
Bullets[plr->iID].erase(resp->iBulletID);
|
||||
}
|
||||
|
||||
void MobManager::followToCombat(Mob *mob) {
|
||||
if (Mobs.find(mob->groupLeader) != Mobs.end()) {
|
||||
Mob* leadMob = Mobs[mob->groupLeader];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (leadMob->groupMember[i] == 0)
|
||||
break;
|
||||
|
||||
if (Mobs.find(leadMob->groupMember[i]) == Mobs.end()) {
|
||||
std::cout << "[WARN] roamingStep: leader can't find a group member!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
Mob* followerMob = Mobs[leadMob->groupMember[i]];
|
||||
|
||||
if (followerMob->state == MobState::COMBAT)
|
||||
continue;
|
||||
|
||||
followerMob->target = mob->target;
|
||||
followerMob->state = MobState::COMBAT;
|
||||
followerMob->nextMovement = getTime();
|
||||
followerMob->nextAttack = 0;
|
||||
|
||||
followerMob->roamX = followerMob->appearanceData.iX;
|
||||
followerMob->roamY = followerMob->appearanceData.iY;
|
||||
followerMob->roamZ = followerMob->appearanceData.iZ;
|
||||
}
|
||||
leadMob->target = mob->target;
|
||||
leadMob->state = MobState::COMBAT;
|
||||
leadMob->nextMovement = getTime();
|
||||
leadMob->nextAttack = 0;
|
||||
|
||||
leadMob->roamX = leadMob->appearanceData.iX;
|
||||
leadMob->roamY = leadMob->appearanceData.iY;
|
||||
leadMob->roamZ = leadMob->appearanceData.iZ;
|
||||
}
|
||||
}
|
||||
|
@ -163,4 +163,6 @@ namespace MobManager {
|
||||
/// returns bullet id
|
||||
int8_t addBullet(Player* plr, bool isGrenade);
|
||||
|
||||
void followToCombat(Mob *mob);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user