mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2025-11-17 15:30:06 +00:00
Merge pull request #118 from JadeShrineMaiden/moblocomotion
Greased up enemies
This commit is contained in:
@@ -7,6 +7,13 @@
|
||||
#include <cmath>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(A,B) ((A)<(B)?(A):(B))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
# define MAX(A,B) ((A)>(B)?(A):(B))
|
||||
#endif
|
||||
|
||||
std::map<int32_t, Mob*> MobManager::Mobs;
|
||||
|
||||
void MobManager::init() {
|
||||
@@ -61,12 +68,19 @@ void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
|
||||
}
|
||||
Mob *mob = Mobs[pktdata[i]];
|
||||
|
||||
int damage = hitMob(sock, mob, 150);
|
||||
std::pair<int,int> damage;
|
||||
|
||||
if (pkt->iNPCCnt > 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].iID = mob->appearanceData.iNPC_ID;
|
||||
respdata[i].iDamage = damage;
|
||||
respdata[i].iDamage = damage.first;
|
||||
respdata[i].iHP = mob->appearanceData.iHP;
|
||||
respdata[i].iHitFlag = 2; // hitscan, not a rocket or a grenade
|
||||
respdata[i].iHitFlag = damage.second; // hitscan, not a rocket or a grenade
|
||||
}
|
||||
|
||||
resp->iBatteryW = plr->batteryW;
|
||||
@@ -94,15 +108,16 @@ void MobManager::npcAttackPc(Mob *mob) {
|
||||
sP_FE2CL_NPC_ATTACK_PCs *pkt = (sP_FE2CL_NPC_ATTACK_PCs*)respbuf;
|
||||
sAttackResult *atk = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_NPC_ATTACK_PCs));
|
||||
|
||||
plr->HP += (int)mob->data["m_iPower"]; // already negative
|
||||
auto damage = getDamage(440 + (int)mob->data["m_iPower"], plr->defense, false, 36 - (int)mob->data["m_iNpcLevel"]);
|
||||
plr->HP -= damage.first;
|
||||
|
||||
pkt->iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||
pkt->iPCCnt = 1;
|
||||
|
||||
atk->iID = plr->iID;
|
||||
atk->iDamage = -(int)mob->data["m_iPower"];
|
||||
atk->iDamage = damage.first;
|
||||
atk->iHP = plr->HP;
|
||||
atk->iHitFlag = 2;
|
||||
atk->iHitFlag = damage.second;
|
||||
|
||||
mob->target->sendPacket((void*)respbuf, P_FE2CL_NPC_ATTACK_PCs, resplen);
|
||||
PlayerManager::sendToViewable(mob->target, (void*)respbuf, P_FE2CL_NPC_ATTACK_PCs, resplen);
|
||||
@@ -275,7 +290,7 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
||||
// movement logic
|
||||
if (mob->nextMovement != 0 && currTime < mob->nextMovement)
|
||||
return;
|
||||
mob->nextMovement = currTime + (int)mob->data["m_iDelayTime"] * 100;
|
||||
mob->nextMovement = currTime + 500;
|
||||
|
||||
int speed = mob->data["m_iRunSpeed"];
|
||||
|
||||
@@ -384,6 +399,11 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
||||
|
||||
void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
||||
// distance between spawn point and current location
|
||||
if (mob->nextMovement != 0 && currTime < mob->nextMovement)
|
||||
return;
|
||||
|
||||
mob->nextMovement = currTime + 500;
|
||||
|
||||
int distance = hypot(mob->appearanceData.iX - mob->spawnX, mob->appearanceData.iY - mob->spawnY);
|
||||
|
||||
if (distance > mob->data["m_iIdleRange"]) {
|
||||
@@ -456,13 +476,21 @@ void MobManager::step(CNServer *serv, time_t currTime) {
|
||||
std::pair<int,int> MobManager::lerp(int x1, int y1, int x2, int y2, int speed) {
|
||||
std::pair<int,int> ret = {};
|
||||
|
||||
speed /= 2;
|
||||
int distance = hypot(x1 - x2, y1 - y2);
|
||||
int lerps = distance / speed;
|
||||
|
||||
// interpolate only the first point
|
||||
float frac = 1.0f / (lerps+1);
|
||||
ret.first = (x1 * (1.0f - frac)) + (x2 * frac);
|
||||
ret.second = (y1 * (1.0f - frac)) + (y2 * frac);
|
||||
if (distance > speed) {
|
||||
int lerps = distance / speed;
|
||||
|
||||
// interpolate only the first point
|
||||
float frac = 1.0f / (lerps);
|
||||
|
||||
ret.first = (x1 + (x2 - x1) * frac);
|
||||
ret.second = (y1 + (y2 - y1) * frac);
|
||||
} else {
|
||||
ret.first = x2;
|
||||
ret.second = y2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -572,3 +600,19 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) {
|
||||
if (currTime - lastHealTime < 4000)
|
||||
lastHealTime = currTime;
|
||||
}
|
||||
|
||||
std::pair<int,int> MobManager::getDamage(int attackPower, int defensePower, bool shouldCrit, int crutchLevel) {
|
||||
|
||||
std::pair<int,int> ret = {};
|
||||
|
||||
int damage = (MAX(40, attackPower - defensePower) * (34 + crutchLevel) + MIN(attackPower, attackPower * attackPower / defensePower) * (36 - crutchLevel)) / 70;
|
||||
ret.first = damage * (rand() % 40 + 80) / 100; // 20% variance
|
||||
ret.second = 1;
|
||||
|
||||
if (shouldCrit && rand() % 20 == 0) {
|
||||
ret.first *= 2; // critical hit
|
||||
ret.second = 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user