Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Abilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ static SkillResult handleSkillBatteryDrain(SkillData* skill, int power, ICombata
if(!blocked) {
boostDrain = (int)(skill->values[0][power] * scalingFactor);
if(boostDrain > plr->batteryW) boostDrain = plr->batteryW;
plr->batteryW -= boostDrain;
plr->subtractCapped(CappedValueType::BATTERY_W, boostDrain);

potionDrain = (int)(skill->values[1][power] * scalingFactor);
if(potionDrain > plr->batteryN) potionDrain = plr->batteryN;
plr->batteryN -= potionDrain;
plr->subtractCapped(CappedValueType::BATTERY_N, potionDrain);
}

sSkillResult_BatteryDrain result{};
Expand Down Expand Up @@ -364,7 +364,7 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*>
ICombatant* src = nullptr;
if(npc.kind == EntityKind::COMBAT_NPC || npc.kind == EntityKind::MOB)
src = dynamic_cast<ICombatant*>(entity);

SkillData* skill = &SkillTable[skillID];

std::vector<SkillResult> results = handleSkill(skill, 0, src, affected);
Expand Down Expand Up @@ -443,7 +443,7 @@ std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* ski
}
}

return targets;
return targets;
}

/* ripped from client (enums emplaced) */
Expand Down
64 changes: 49 additions & 15 deletions src/BuiltinCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,22 @@ static void setValuePlayer(CNSocket* sock, CNPacketData* data) {
case CN_GM_SET_VALUE_TYPE__HP:
response.iSetValue = plr->HP = setData->iSetValue;
break;
case CN_GM_SET_VALUE_TYPE__WEAPON_BATTERY :
plr->batteryW = setData->iSetValue;

// caps
if (plr->batteryW > 9999)
plr->batteryW = 9999;

case CN_GM_SET_VALUE_TYPE__WEAPON_BATTERY:
plr->setCapped(CappedValueType::BATTERY_W, setData->iSetValue);
response.iSetValue = plr->batteryW;
break;
case CN_GM_SET_VALUE_TYPE__NANO_BATTERY:
plr->batteryN = setData->iSetValue;

// caps
if (plr->batteryN > 9999)
plr->batteryN = 9999;

plr->setCapped(CappedValueType::BATTERY_N, setData->iSetValue);
response.iSetValue = plr->batteryN;
break;
case CN_GM_SET_VALUE_TYPE__FUSION_MATTER:
Missions::updateFusionMatter(sock, setData->iSetValue - plr->fusionmatter);
plr->setCapped(CappedValueType::FUSIONMATTER, setData->iSetValue);
Missions::updateFusionMatter(sock);
response.iSetValue = plr->fusionmatter;
break;
case CN_GM_SET_VALUE_TYPE__CANDY:
response.iSetValue = plr->money = setData->iSetValue;
plr->setCapped(CappedValueType::TAROS, setData->iSetValue);
response.iSetValue = plr->money;
break;
case CN_GM_SET_VALUE_TYPE__SPEED:
case CN_GM_SET_VALUE_TYPE__JUMP:
Expand Down Expand Up @@ -148,6 +140,47 @@ static void setGMSpecialOnOff(CNSocket *sock, CNPacketData *data) {
// this is only used for muting players, so no need to update the client since that logic is server-side
}

static void setGMRewardRate(CNSocket *sock, CNPacketData *data) {
Player *plr = PlayerManager::getPlayer(sock);

// access check
if (plr->accountLevel > 30)
return;

auto req = (sP_CL2FE_GM_REQ_REWARD_RATE*)data->buf;

if (req->iGetSet != 0) {
double *rate = plr->rateT;

switch (req->iRewardType) {
case REWARD_TYPE_TAROS:
rate = plr->rateT;
break;
case REWARD_TYPE_FUSIONMATTER:
rate = plr->rateF;
break;
}

switch (req->iRewardRateIndex) {
case RATE_SLOT_ALL:
for (int i = 0; i < 5; i++)
rate[i] = req->iSetRateValue;
break;
case RATE_SLOT_COMBAT:
case RATE_SLOT_MISSION:
case RATE_SLOT_EGG:
case RATE_SLOT_RACING:
rate[req->iRewardRateIndex] = req->iSetRateValue;
break;
}
}

INITSTRUCT(sP_FE2CL_GM_REP_REWARD_RATE_SUCC, resp);
memcpy(resp.afRewardRate_Taros, plr->rateT, sizeof(resp.afRewardRate_Taros));
memcpy(resp.afRewardRate_FusionMatter, plr->rateF, sizeof(resp.afRewardRate_FusionMatter));
sock->sendPacket(resp, P_FE2CL_GM_REP_REWARD_RATE_SUCC);
}

static void locatePlayer(CNSocket *sock, CNPacketData *data) {
Player *plr = PlayerManager::getPlayer(sock);

Expand Down Expand Up @@ -371,6 +404,7 @@ void BuiltinCommands::init() {

REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH, setGMSpecialSwitchPlayer);
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF, setGMSpecialOnOff);
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_REWARD_RATE, setGMRewardRate);

REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_LOCATION, locatePlayer);
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_KICK_PLAYER, kickPlayer);
Expand Down
15 changes: 4 additions & 11 deletions src/Combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ EntityRef CombatNPC::getRef() {
}

void CombatNPC::step(time_t currTime) {

if(stateHandlers.find(state) != stateHandlers.end())
stateHandlers[state](this, currTime);
else {
Expand Down Expand Up @@ -441,11 +441,7 @@ static void pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
damage = getDamage(damage.first, (int)mob->data["m_iProtection"], true, (plr->batteryW > 6 + difficulty),
Nanos::nanoStyle(plr->activeNano), (int)mob->data["m_iNpcStyle"], difficulty);

if (plr->batteryW >= 6 + difficulty)
plr->batteryW -= 6 + difficulty;
else
plr->batteryW = 0;

plr->subtractCapped(CappedValueType::BATTERY_W, 6 + difficulty);
damage.first = mob->takeDamage(sock, damage.first);

respdata[i].iID = mob->id;
Expand Down Expand Up @@ -690,10 +686,7 @@ static void pcAttackChars(CNSocket *sock, CNPacketData *data) {
Nanos::nanoStyle(plr->activeNano), (int)mob->data["m_iNpcStyle"], difficulty);
}

if (plr->batteryW >= 6 + plr->level)
plr->batteryW -= 6 + plr->level;
else
plr->batteryW = 0;
plr->subtractCapped(CappedValueType::BATTERY_W, 6 + plr->level);

damage.first = target->takeDamage(sock, damage.first);

Expand Down Expand Up @@ -742,7 +735,7 @@ static int8_t addBullet(Player* plr, bool isGrenade) {
toAdd.weaponBoost = plr->batteryW > 0;
if (toAdd.weaponBoost) {
int boostCost = Rand::rand(11) + 20;
plr->batteryW = boostCost > plr->batteryW ? 0 : plr->batteryW - boostCost;
plr->subtractCapped(CappedValueType::BATTERY_W, boostCost);
}

Bullets[plr->iID][findId] = toAdd;
Expand Down
6 changes: 3 additions & 3 deletions src/Email.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ static void emailReceiveTaros(CNSocket* sock, CNPacketData* data) {

Database::EmailData email = Database::getEmail(plr->iID, pkt->iEmailIndex);
// money transfer
plr->money += email.Taros;
plr->addCapped(CappedValueType::TAROS, email.Taros);
email.Taros = 0;
// update Taros in email
Database::updateEmailContent(&email);
Expand Down Expand Up @@ -274,7 +274,7 @@ static void emailSend(CNSocket* sock, CNPacketData* data) {
}

int cost = pkt->iCash + 50 + 20 * attachments.size(); // attached taros + postage
plr->money -= cost;
plr->subtractCapped(CappedValueType::TAROS, cost);
Database::EmailData email = {
(int)pkt->iTo_PCUID, // PlayerId
Database::getNextEmailIndex(pkt->iTo_PCUID), // MsgIndex
Expand All @@ -291,7 +291,7 @@ static void emailSend(CNSocket* sock, CNPacketData* data) {
};

if (!Database::sendEmail(&email, attachments, plr)) {
plr->money += cost; // give money back
plr->addCapped(CappedValueType::TAROS, cost); // give money back
// give items back
while (!attachments.empty()) {
sItemBase attachment = attachments.back();
Expand Down
106 changes: 106 additions & 0 deletions src/Entities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,112 @@ sPCAppearanceData Player::getAppearanceData() {
return data;
}

bool Player::hasQuestBoost() const {
const sItemBase& booster = Equip[10];
return booster.iID == 153 && booster.iOpt > 0;
}

bool Player::hasHunterBoost() const {
const sItemBase& booster = Equip[11];
return booster.iID == 154 && booster.iOpt > 0;
}

bool Player::hasRacerBoost() const {
const sItemBase& booster = Equip[9];
return booster.iID == 155 && booster.iOpt > 0;
}

bool Player::hasSuperBoost() const {
return Player::hasQuestBoost() && Player::hasHunterBoost() && Player::hasRacerBoost();
}

static int32_t getCap(CappedValueType type) {
switch (type) {
case CappedValueType::TAROS:
return PC_CANDY_MAX;
case CappedValueType::FUSIONMATTER:
return PC_FUSIONMATTER_MAX;
case CappedValueType::BATTERY_W:
return PC_BATTERY_MAX;
case CappedValueType::BATTERY_N:
return PC_BATTERY_MAX;
case CappedValueType::TAROS_IN_TRADE:
return PC_CANDY_MAX;
default:
return INT32_MAX;
}
}

static int32_t *getCappedValue(Player *player, CappedValueType type) {
switch (type) {
case CappedValueType::TAROS:
return &player->money;
case CappedValueType::FUSIONMATTER:
return &player->fusionmatter;
case CappedValueType::BATTERY_W:
return &player->batteryW;
case CappedValueType::BATTERY_N:
return &player->batteryN;
case CappedValueType::TAROS_IN_TRADE:
return &player->moneyInTrade;
default:
return nullptr;
}
}

void Player::addCapped(CappedValueType type, int32_t diff) {
if (diff <= 0)
return;

int32_t max = getCap(type);
int32_t *value = getCappedValue(this, type);

if (value == nullptr)
return;

if (diff > max)
diff = max;

if (*value + diff > max)
*value = max;
else
*value += diff;
}

void Player::subtractCapped(CappedValueType type, int32_t diff) {
if (diff <= 0)
return;

int32_t max = getCap(type);
int32_t *value = getCappedValue(this, type);

if (value == nullptr)
return;

if (diff > max)
diff = max;

if (*value - diff < 0)
*value = 0;
else
*value -= diff;
}

void Player::setCapped(CappedValueType type, int32_t value) {
int32_t max = getCap(type);
int32_t *valToSet = getCappedValue(this, type);

if (valToSet == nullptr)
return;

if (value < 0)
value = 0;
else if (value > max)
value = max;

*valToSet = value;
}

// TODO: this is less effiecient than it was, because of memset()
void Player::enterIntoViewOf(CNSocket *sock) {
INITSTRUCT(sP_FE2CL_PC_NEW, pkt);
Expand Down
Loading