#include "handlers.h"
#include "map.hpp"
#include "party.hpp"
#include <iostream>
using namespace std;
CLIENT_F_FUNC(Spell)
{
PacketBuilder reply;
PacketBuilder builder;
switch (action)
{
case PACKET_REQUEST: // Player using an spell
{
if (this->state < EOClient::PlayingModal) return false;
int spellid = reader.GetShort();
int unk1 = reader.GetByte();
int unk2 = reader.GetByte();
int unk3 = reader.GetByte();
int unk4 = reader.GetByte();
#ifdef DEBUG
cout << spellid << endl;
cout << unk1 << endl;
cout << unk2 << endl;
cout << unk3 << endl;
cout << unk4 << endl;
#endif
builder.SetID(PACKET_SPELL, PACKET_REQUEST);
builder.AddShort(this->player->id);
builder.AddShort(spellid);
UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character , character)
{
character->player->client->SendBuilder(builder);
}
}
break;
case PACKET_CASTSELF: // Player using an spell
{
if (this->state < EOClient::PlayingModal) return false;
int direction = reader.GetChar();
int spellid = reader.GetByte();
int unk1 = reader.GetShort();
int unk2 = reader.GetShort();
#ifdef DEBUG
cout << direction << endl;
cout << spellid << endl;
cout << unk1 << endl;
cout << unk2 << endl;
#endif
ESF_Data *spell = this->server->world->esf->Get(spellid);
if (spell->spell_effect == ESF::Heal)
{
int hpgain = spell->hp;
int tpgain = spell->tp;
if (this->server->world->config["LimitDamage"])
{
hpgain = std::min(hpgain, this->player->character->maxhp - this->player->character->hp);
tpgain = std::min(tpgain, this->player->character->maxtp - this->player->character->tp);
}
hpgain = std::max(hpgain, 0);
tpgain = std::max(tpgain, 0);
this->player->character->hp += hpgain;
this->player->character->tp -= tpgain;
if (!this->server->world->config["LimitDamage"])
{
this->player->character->hp = std::min(this->player->character->hp, this->player->character->maxhp);
this->player->character->tp = std::min(this->player->character->tp, this->player->character->maxtp);
}
reply.SetID(PACKET_SPELL, PACKET_CASTSELF);
reply.AddShort(this->player->id);
reply.AddShort(spellid); //spell id
reply.AddInt(spell->hp); //Displays heal amount
reply.AddChar(int(double(this->player->character->hp) / double(this->player->character->maxhp) * 100.0));
reply.AddShort(this->player->character->hp);
reply.AddShort(this->player->character->tp);
reply.AddShort(direction);//?
builder.SetID(PACKET_SPELL, PACKET_CASTSELF);
builder.AddShort(this->player->id);
builder.AddShort(spellid);
builder.AddInt(spell->hp);
builder.AddChar(int(double(player->character->hp) / double(player->character->maxhp) * 100.0));
UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character , character)
{
if (*character != this->player->character && this->player->character->InRange(*character))
{
character->player->client->SendBuilder(builder);
}
}
if (this->player->character->party)
{
this->player->character->party->UpdateHP(this->player->character);
}
CLIENT_SEND(reply);
}
}
break;
case PACKET_CASTOTHER:
{
if (this->state < EOClient::PlayingModal) return false;
int unk0 = reader.GetByte();
int unk1 = reader.GetByte();
int something1 = reader.GetShort();
int spellid = reader.GetShort();
int targetid = reader.GetShort();
#ifdef DEBUG
cout << unk0 << endl;
cout << unk1 << endl;
cout << something1 << endl;
cout << spellid << endl;
cout << targetid << endl;
#endif
ESF_Data *spell = this->server->world->esf->Get(spellid);
cout << spell->type << endl;
if (spell->spell_effect == ESF::Heal && spell->type == ESF::Normal)
{
Character *victim = this->server->world->GetCharacterPID(targetid);
int hpgain = spell->hp;
int tpgain = spell->tp;
if (victim && victim->player->id == this->player->id)
{
if (this->server->world->config["LimitDamage"])
{
hpgain = std::min(hpgain, this->player->character->maxhp - this->player->character->hp);
tpgain = std::min(tpgain, this->player->character->maxtp - this->player->character->tp);
}
hpgain = std::max(hpgain, 0);
tpgain = std::max(tpgain, 0);
this->player->character->hp += hpgain;
this->player->character->tp -= tpgain;
if (!this->server->world->config["LimitDamage"])
{
this->player->character->hp = std::min(this->player->character->hp, this->player->character->maxhp);
this->player->character->tp = std::min(this->player->character->tp, this->player->character->maxtp);
}
builder.SetID(PACKET_SPELL, PACKET_CASTOTHER);
builder.AddShort(this->player->id);
builder.AddShort(this->player->id);
builder.AddByte(unk0);
builder.AddShort(spellid);
builder.AddInt(spell->hp);
builder.AddChar(int(double(this->player->character->hp) / double(this->player->character->maxhp) * 100.0));
builder.AddShort(this->player->character->hp);
UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character , character)
{
character->player->client->SendBuilder(builder);
}
builder.Reset();
builder.SetID(PACKET_SPELL, PACKET_REPLY);
builder.AddShort(spellid);
builder.AddShort(this->player->character->hp);
builder.AddShort(this->player->character->tp);
this->player->client->SendBuilder(builder);
}
else if (victim && victim->player->id != this->player->id)
{
if (this->server->world->config["LimitDamage"])
{
hpgain = std::min(hpgain, victim->maxhp - victim->hp);
tpgain = std::min(tpgain, victim->maxtp - victim->tp);
}
hpgain = std::max(hpgain, 0);
tpgain = std::max(tpgain, 0);
victim->hp += hpgain;
this->player->character->tp -= tpgain;
if (!this->server->world->config["LimitDamage"])
{
victim->hp = std::min(victim->hp, victim->maxhp);
victim->tp = std::min(victim->tp, victim->maxtp);
}
builder.SetID(PACKET_SPELL, PACKET_CASTOTHER);
builder.AddShort(targetid);
builder.AddShort(this->player->id);
builder.AddByte(unk0);
builder.AddShort(spellid);
builder.AddInt(spell->hp);
builder.AddChar(int(double(victim->hp) / double(victim->maxhp) * 100.0));
builder.AddShort(victim->hp);
UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character , character)
{
character->player->client->SendBuilder(builder);
}
builder.Reset();
builder.SetID(PACKET_SPELL, PACKET_REPLY);
builder.AddShort(spellid);
builder.AddShort(this->player->character->hp);
builder.AddShort(this->player->character->tp);
this->player->client->SendBuilder(builder);
}
}
else if (spell->spell_effect == ESF::Damage && spell->type == ESF::Normal)
{
if (this->player->character->HasSpell(spellid) == spellid)
{
int tpused = spell->tp;
if (this->server->world->config["LimitDamage"])
{
tpused = std::min(tpused, this->player->character->maxtp - this->player->character->tp);
}
tpused = std::max(tpused, 0);
this->player->character->tp -= tpused;
if (!this->server->world->config["LimitDamage"])
{
this->player->character->tp = std::min(this->player->character->tp, this->player->character->maxtp);
}
this->player->character->AttackSpell(spellid, targetid);
}
}
}
break;
case PACKET_EXP:
{
if (this->state < EOClient::PlayingModal) return false;
int spellid = reader.GetShort();
int unk0 = reader.GetByte();
int unk1 = reader.GetByte();
int unk2 = reader.GetByte();
int unk3 = reader.GetByte();
#ifdef DEBUG
cout << spellid << endl;
cout << unk0<< endl;
cout << unk1 << endl;
cout << unk2 << endl;
cout << unk3 << endl;
#endif
ESF_Data *spell = this->server->world->esf->Get(spellid);
if (spell->spell_effect == ESF::Heal)
{
int hpgain = spell->hp;
int tpgain = spell->tp;
if (this->server->world->config["LimitDamage"])
{
hpgain = std::min(hpgain, this->player->character->maxhp - this->player->character->hp);
tpgain = std::min(tpgain, this->player->character->maxtp - this->player->character->tp);
}
hpgain = std::max(hpgain, 0);
tpgain = std::max(tpgain, 0);
this->player->character->hp += tpgain;
this->player->character->tp -= tpgain;
if (!this->server->world->config["LimitDamage"])
{
this->player->character->hp = std::min(this->player->character->hp, this->player->character->maxhp);
this->player->character->tp = std::min(this->player->character->tp, this->player->character->maxtp);
}
reply.SetID(PACKET_SPELL, PACKET_EXP);
reply.AddShort(spellid);
reply.AddShort(this->player->id);
reply.AddShort(this->player->character->tp);
reply.AddShort(spell->hp);
reply.AddShort(this->player->id);
reply.AddChar(int(double(player->character->hp) / double(player->character->maxhp) * 100.0));
reply.AddShort(this->player->character->hp);
UTIL_PTR_VECTOR_FOREACH(this->player->character->party->members, Character, member)
{
if(member->map == this->player->character->map)
{
if (this->server->world->config["LimitDamage"])
{
hpgain = std::min(hpgain, member->maxhp - member->hp);
}
hpgain = std::max(hpgain, 0);
member->hp += hpgain;
if (!this->server->world->config["LimitDamage"])
{
member->hp = std::min(member->hp, member->maxhp);
}
reply.AddShort(member->player->id);
reply.AddChar(int(double(member->hp) / double(member->maxhp) * 100.0));
reply.AddShort(member->hp);
}
}
UTIL_PTR_LIST_FOREACH(this->player->character->map->characters, Character , character)
{
character->player->client->SendBuilder(reply);
}
}
}
break;
default:
return false;
}
return true;
}