mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 18:51:29 +00:00
Reworked RespawnFromHover framework to allow future customization (scripting) of respawn options.
Added event_respawn to be triggered when a client respawns from hover into the current zone (may not be set up correctly!).
This commit is contained in:
parent
e811e3975b
commit
c5e4cf35c0
188
zone/client.cpp
188
zone/client.cpp
@ -319,6 +319,8 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
MaxXTargets = 5;
|
MaxXTargets = 5;
|
||||||
XTargetAutoAddHaters = true;
|
XTargetAutoAddHaters = true;
|
||||||
LoadAccountFlags();
|
LoadAccountFlags();
|
||||||
|
|
||||||
|
initial_respawn_selection = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client() {
|
Client::~Client() {
|
||||||
@ -415,6 +417,8 @@ Client::~Client() {
|
|||||||
safe_delete_array(adv_requested_data);
|
safe_delete_array(adv_requested_data);
|
||||||
safe_delete_array(adv_data);
|
safe_delete_array(adv_data);
|
||||||
|
|
||||||
|
ClearRespawnOptions();
|
||||||
|
|
||||||
numclients--;
|
numclients--;
|
||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
if(zone)
|
if(zone)
|
||||||
@ -4310,45 +4314,68 @@ void Client::SendRespawnBinds()
|
|||||||
// Client will respond with a 4 byte packet that includes the number of the selection made
|
// Client will respond with a 4 byte packet that includes the number of the selection made
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//If no options have been given, default to Bind + Rez
|
||||||
|
if (respawn_options.empty())
|
||||||
|
{
|
||||||
|
BindStruct* b = &m_pp.binds[0];
|
||||||
|
RespawnOption opt;
|
||||||
|
opt.name = "Bind Location";
|
||||||
|
opt.zoneid = b->zoneId;
|
||||||
|
opt.x = b->x;
|
||||||
|
opt.y = b->y;
|
||||||
|
opt.z = b->z;
|
||||||
|
opt.heading = b->heading;
|
||||||
|
respawn_options.push_front(opt);
|
||||||
|
}
|
||||||
|
//Rez is always added at the end
|
||||||
|
RespawnOption rez;
|
||||||
|
rez.name = "Resurrect";
|
||||||
|
rez.zoneid = zone->GetZoneID();
|
||||||
|
rez.x = GetX();
|
||||||
|
rez.y = GetY();
|
||||||
|
rez.z = GetZ();
|
||||||
|
rez.heading = GetHeading();
|
||||||
|
respawn_options.push_back(rez);
|
||||||
|
|
||||||
const char* BindName = "Bind Location";
|
int num_options = respawn_options.size();
|
||||||
const char* Resurrect = "Resurrect";
|
uint32 PacketLength = 17 + (26 * num_options); //Header size + per-option invariant size
|
||||||
|
|
||||||
int PacketLength;
|
std::list<RespawnOption>::iterator itr;
|
||||||
|
RespawnOption* opt;
|
||||||
|
|
||||||
PacketLength = 17 + (26 * 2) + strlen(BindName) + strlen(Resurrect); // SoF
|
//Find string size for each option
|
||||||
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
|
{
|
||||||
|
opt = &(*itr);
|
||||||
|
PacketLength += opt->name.size() + 1; //+1 for cstring
|
||||||
|
}
|
||||||
|
|
||||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength);
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength);
|
||||||
|
char* buffer = (char*)outapp->pBuffer;
|
||||||
|
|
||||||
char *Buffer = (char *)outapp->pBuffer;
|
//Packet header
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, initial_respawn_selection); //initial selection (from 0)
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, RuleI(Character, RespawnFromHoverTimer) * 1000);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, 0); //unknown
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, num_options); //number of options to display
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Unknown
|
//Individual options
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, RuleI(Character, RespawnFromHoverTimer) * 1000);
|
int count = 0;
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Unknown
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 2); // Two options, Bind or Rez
|
{
|
||||||
|
opt = &(*itr);
|
||||||
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, count++); //option num (from 0)
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Entry 0
|
VARSTRUCT_ENCODE_TYPE(uint32, buffer, opt->zoneid);
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, m_pp.binds[0].zoneId);
|
VARSTRUCT_ENCODE_TYPE(float, buffer, opt->x);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].x);
|
VARSTRUCT_ENCODE_TYPE(float, buffer, opt->y);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].y);
|
VARSTRUCT_ENCODE_TYPE(float, buffer, opt->z);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].z);
|
VARSTRUCT_ENCODE_TYPE(float, buffer, opt->heading);
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, m_pp.binds[0].heading);
|
VARSTRUCT_ENCODE_STRING(buffer, opt->name.c_str());
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, BindName);
|
VARSTRUCT_ENCODE_TYPE(uint8, buffer, (count == num_options)); //is this one Rez (the last option)?
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0);
|
}
|
||||||
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // Entry 1
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, zone->GetZoneID());
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, GetX());
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, GetY());
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, GetZ());
|
|
||||||
VARSTRUCT_ENCODE_TYPE(float, Buffer, GetHeading());
|
|
||||||
VARSTRUCT_ENCODE_STRING(Buffer, Resurrect);
|
|
||||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1);
|
|
||||||
|
|
||||||
QueuePacket(outapp);
|
QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7734,3 +7761,104 @@ void Client::TryItemTick(int slot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::AddRespawnOption(std::string option_name, uint32 zoneid, float x, float y, float z, float heading, bool initial_selection, int8 position)
|
||||||
|
{
|
||||||
|
//If respawn window is already open, any changes would create an inconsistency with the client
|
||||||
|
if (IsHoveringForRespawn()) { return; }
|
||||||
|
|
||||||
|
if (zoneid == 0)
|
||||||
|
zoneid = zone->GetZoneID();
|
||||||
|
|
||||||
|
//Create respawn option
|
||||||
|
RespawnOption res_opt;
|
||||||
|
res_opt.name = option_name;
|
||||||
|
res_opt.zoneid = zoneid;
|
||||||
|
res_opt.x = x;
|
||||||
|
res_opt.y = y;
|
||||||
|
res_opt.z = z;
|
||||||
|
res_opt.heading = heading;
|
||||||
|
|
||||||
|
if (position == -1 || position >= respawn_options.size())
|
||||||
|
{
|
||||||
|
//No position specified, or specified beyond the end, simply append
|
||||||
|
respawn_options.push_back(res_opt);
|
||||||
|
//Make this option the initial selection for the window if desired
|
||||||
|
if (initial_selection)
|
||||||
|
initial_respawn_selection = static_cast<uint8>(respawn_options.size()) - 1;
|
||||||
|
}
|
||||||
|
else if (position == 0)
|
||||||
|
{
|
||||||
|
respawn_options.push_front(res_opt);
|
||||||
|
if (initial_selection)
|
||||||
|
initial_respawn_selection = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Insert new option between existing options
|
||||||
|
std::list<RespawnOption>::iterator itr;
|
||||||
|
uint8 pos = 0;
|
||||||
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (pos++ == position)
|
||||||
|
{
|
||||||
|
respawn_options.insert(itr,res_opt);
|
||||||
|
//Make this option the initial selection for the window if desired
|
||||||
|
if (initial_selection)
|
||||||
|
initial_respawn_selection = pos;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::RemoveRespawnOption(std::string option_name)
|
||||||
|
{
|
||||||
|
//If respawn window is already open, any changes would create an inconsistency with the client
|
||||||
|
if (IsHoveringForRespawn() || respawn_options.empty()) { return false; }
|
||||||
|
|
||||||
|
bool had = false;
|
||||||
|
RespawnOption* opt;
|
||||||
|
std::list<RespawnOption>::iterator itr;
|
||||||
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
|
{
|
||||||
|
opt = &(*itr);
|
||||||
|
if (opt->name.compare(option_name) == 0)
|
||||||
|
{
|
||||||
|
respawn_options.erase(itr);
|
||||||
|
had = true;
|
||||||
|
//could be more with the same name, so keep going...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return had;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::RemoveRespawnOption(uint8 position)
|
||||||
|
{
|
||||||
|
//If respawn window is already open, any changes would create an inconsistency with the client
|
||||||
|
if (IsHoveringForRespawn() || respawn_options.empty()) { return false; }
|
||||||
|
|
||||||
|
//Easy cases first...
|
||||||
|
if (position == 0)
|
||||||
|
{
|
||||||
|
respawn_options.pop_front();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (position == (respawn_options.size() - 1))
|
||||||
|
{
|
||||||
|
respawn_options.pop_back();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<RespawnOption>::iterator itr;
|
||||||
|
uint8 pos = 0;
|
||||||
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (pos++ == position)
|
||||||
|
{
|
||||||
|
respawn_options.erase(itr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -179,6 +179,16 @@ struct XTarget_Struct
|
|||||||
char Name[65];
|
char Name[65];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RespawnOption
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
uint32 zoneid;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
float heading;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000;
|
const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000;
|
||||||
|
|
||||||
@ -1043,6 +1053,11 @@ public:
|
|||||||
bool MoveItemToInventory(ItemInst *BInst, bool UpdateClient = false);
|
bool MoveItemToInventory(ItemInst *BInst, bool UpdateClient = false);
|
||||||
void HandleRespawnFromHover(uint32 Option);
|
void HandleRespawnFromHover(uint32 Option);
|
||||||
bool IsHoveringForRespawn() { return RespawnFromHoverTimer.Enabled(); }
|
bool IsHoveringForRespawn() { return RespawnFromHoverTimer.Enabled(); }
|
||||||
|
std::list<RespawnOption> respawn_options;
|
||||||
|
void AddRespawnOption(std::string option_name, uint32 zoneid, float x, float y, float z, float h = 0, bool initial_selection = false, int8 position = -1);
|
||||||
|
bool RemoveRespawnOption(std::string option_name);
|
||||||
|
bool RemoveRespawnOption(uint8 position);
|
||||||
|
void ClearRespawnOptions() { respawn_options.clear(); }
|
||||||
void SetPendingRezzData(int XP, uint32 DBID, uint16 SpellID, const char *CorpseName) { PendingRezzXP = XP; PendingRezzDBID = DBID; PendingRezzSpellID = SpellID; PendingRezzCorpseName = CorpseName; }
|
void SetPendingRezzData(int XP, uint32 DBID, uint16 SpellID, const char *CorpseName) { PendingRezzXP = XP; PendingRezzDBID = DBID; PendingRezzSpellID = SpellID; PendingRezzCorpseName = CorpseName; }
|
||||||
bool IsRezzPending() { return PendingRezzSpellID > 0; }
|
bool IsRezzPending() { return PendingRezzSpellID > 0; }
|
||||||
void ClearHover();
|
void ClearHover();
|
||||||
@ -1449,6 +1464,8 @@ private:
|
|||||||
|
|
||||||
Timer ItemTickTimer;
|
Timer ItemTickTimer;
|
||||||
std::map<std::string,std::string> accountflags;
|
std::map<std::string,std::string> accountflags;
|
||||||
|
|
||||||
|
uint8 initial_respawn_selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|||||||
@ -2040,87 +2040,139 @@ void Client::HandleRespawnFromHover(uint32 Option)
|
|||||||
{
|
{
|
||||||
RespawnFromHoverTimer.Disable();
|
RespawnFromHoverTimer.Disable();
|
||||||
|
|
||||||
if(Option == 1) // Resurrect
|
RespawnOption* chosen = nullptr;
|
||||||
|
bool is_rez = false;
|
||||||
|
|
||||||
|
//Find the selected option
|
||||||
|
if (Option == 0)
|
||||||
{
|
{
|
||||||
if((PendingRezzXP < 0) || (PendingRezzSpellID == 0))
|
chosen = &respawn_options.front();
|
||||||
{
|
|
||||||
_log(SPELLS__REZ, "Unexpected Rezz from hover request.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SetHP(GetMaxHP() / 5);
|
|
||||||
|
|
||||||
Corpse* corpse = entity_list.GetCorpseByName(PendingRezzCorpseName.c_str());
|
|
||||||
|
|
||||||
if(corpse)
|
|
||||||
{
|
|
||||||
x_pos = corpse->GetX();
|
|
||||||
y_pos = corpse->GetY();
|
|
||||||
z_pos = corpse->GetZ();
|
|
||||||
}
|
|
||||||
|
|
||||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10);
|
|
||||||
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
|
|
||||||
|
|
||||||
gmg->bind_zone_id = zone->GetZoneID();
|
|
||||||
gmg->bind_instance_id = zone->GetInstanceID();
|
|
||||||
gmg->x = GetX();
|
|
||||||
gmg->y = GetY();
|
|
||||||
gmg->z = GetZ();
|
|
||||||
gmg->heading = GetHeading();
|
|
||||||
strcpy(gmg->zone_name, "Resurrect");
|
|
||||||
|
|
||||||
FastQueuePacket(&outapp);
|
|
||||||
|
|
||||||
ClearHover();
|
|
||||||
SendHPUpdate();
|
|
||||||
OPRezzAnswer(1, PendingRezzSpellID, zone->GetZoneID(), zone->GetInstanceID(), GetX(), GetY(), GetZ());
|
|
||||||
|
|
||||||
if (corpse && corpse->IsCorpse()) {
|
|
||||||
_log(SPELLS__REZ, "Hover Rez in zone %s for corpse %s",
|
|
||||||
zone->GetShortName(), PendingRezzCorpseName.c_str());
|
|
||||||
|
|
||||||
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
|
|
||||||
|
|
||||||
corpse->Rezzed(true);
|
|
||||||
corpse->CompleteRezz();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (Option == (respawn_options.size() - 1))
|
||||||
// Respawn at Bind Point.
|
|
||||||
//
|
|
||||||
if(m_pp.binds[0].zoneId == zone->GetZoneID())
|
|
||||||
{
|
{
|
||||||
PendingRezzSpellID = 0;
|
chosen = &respawn_options.back();
|
||||||
|
is_rez = true; //Rez must always be the last option
|
||||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 14);
|
|
||||||
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
|
|
||||||
|
|
||||||
gmg->bind_zone_id = m_pp.binds[0].zoneId;
|
|
||||||
gmg->x = m_pp.binds[0].x;
|
|
||||||
gmg->y = m_pp.binds[0].y;
|
|
||||||
gmg->z = m_pp.binds[0].z;
|
|
||||||
gmg->heading = 0;
|
|
||||||
strcpy(gmg->zone_name, "Bind Location");
|
|
||||||
|
|
||||||
FastQueuePacket(&outapp);
|
|
||||||
|
|
||||||
CalcBonuses();
|
|
||||||
SetHP(GetMaxHP());
|
|
||||||
SetMana(GetMaxMana());
|
|
||||||
SetEndurance(GetMaxEndurance());
|
|
||||||
|
|
||||||
x_pos = m_pp.binds[0].x;
|
|
||||||
y_pos = m_pp.binds[0].y;
|
|
||||||
z_pos = m_pp.binds[0].z;
|
|
||||||
|
|
||||||
ClearHover();
|
|
||||||
entity_list.RefreshClientXTargets(this);
|
|
||||||
SendHPUpdate();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::list<RespawnOption>::iterator itr;
|
||||||
|
uint32 pos = 0;
|
||||||
|
for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (pos++ == Option)
|
||||||
|
{
|
||||||
|
chosen = &(*itr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If they somehow chose an option they don't have, just send them to bind
|
||||||
|
RespawnOption default_to_bind; //must keep in scope!
|
||||||
|
if (!chosen)
|
||||||
|
{
|
||||||
|
/* put error logging here */
|
||||||
|
BindStruct* b = &m_pp.binds[0];
|
||||||
|
default_to_bind.name = "Bind Location";
|
||||||
|
default_to_bind.zoneid = b->zoneId;
|
||||||
|
default_to_bind.x = b->x;
|
||||||
|
default_to_bind.y = b->y;
|
||||||
|
default_to_bind.z = b->z;
|
||||||
|
default_to_bind.heading = b->heading;
|
||||||
|
chosen = &default_to_bind;
|
||||||
|
is_rez = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosen->zoneid == zone->GetZoneID()) //If they should respawn in the current zone...
|
||||||
|
{
|
||||||
|
if (is_rez)
|
||||||
|
{
|
||||||
|
if (PendingRezzXP < 0 || PendingRezzSpellID == 0)
|
||||||
|
{
|
||||||
|
_log(SPELLS__REZ, "Unexpected Rezz from hover request.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetHP(GetMaxHP() / 5);
|
||||||
|
|
||||||
|
Corpse* corpse = entity_list.GetCorpseByName(PendingRezzCorpseName.c_str());
|
||||||
|
|
||||||
|
if (corpse)
|
||||||
|
{
|
||||||
|
x_pos = corpse->GetX();
|
||||||
|
y_pos = corpse->GetY();
|
||||||
|
z_pos = corpse->GetZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10);
|
||||||
|
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
|
||||||
|
|
||||||
|
gmg->bind_zone_id = zone->GetZoneID();
|
||||||
|
gmg->bind_instance_id = zone->GetInstanceID();
|
||||||
|
gmg->x = GetX();
|
||||||
|
gmg->y = GetY();
|
||||||
|
gmg->z = GetZ();
|
||||||
|
gmg->heading = GetHeading();
|
||||||
|
strcpy(gmg->zone_name, "Resurrect");
|
||||||
|
|
||||||
|
FastQueuePacket(&outapp);
|
||||||
|
|
||||||
|
ClearHover();
|
||||||
|
SendHPUpdate();
|
||||||
|
OPRezzAnswer(1, PendingRezzSpellID, zone->GetZoneID(), zone->GetInstanceID(), GetX(), GetY(), GetZ());
|
||||||
|
|
||||||
|
if (corpse && corpse->IsCorpse())
|
||||||
|
{
|
||||||
|
_log(SPELLS__REZ, "Hover Rez in zone %s for corpse %s",
|
||||||
|
zone->GetShortName(), PendingRezzCorpseName.c_str());
|
||||||
|
|
||||||
|
_log(SPELLS__REZ, "Found corpse. Marking corpse as rezzed.");
|
||||||
|
|
||||||
|
corpse->Rezzed(true);
|
||||||
|
corpse->CompleteRezz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //Not rez
|
||||||
|
{
|
||||||
|
PendingRezzSpellID = 0;
|
||||||
|
|
||||||
|
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + chosen->name.length() + 1);
|
||||||
|
ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer;
|
||||||
|
|
||||||
|
gmg->bind_zone_id = zone->GetZoneID();
|
||||||
|
gmg->x = chosen->x;
|
||||||
|
gmg->y = chosen->y;
|
||||||
|
gmg->z = chosen->z;
|
||||||
|
gmg->heading = chosen->heading;
|
||||||
|
strcpy(gmg->zone_name, chosen->name.c_str());
|
||||||
|
|
||||||
|
FastQueuePacket(&outapp);
|
||||||
|
|
||||||
|
CalcBonuses();
|
||||||
|
SetHP(GetMaxHP());
|
||||||
|
SetMana(GetMaxMana());
|
||||||
|
SetEndurance(GetMaxEndurance());
|
||||||
|
|
||||||
|
x_pos = chosen->x;
|
||||||
|
y_pos = chosen->y;
|
||||||
|
z_pos = chosen->z;
|
||||||
|
heading = chosen->heading;
|
||||||
|
|
||||||
|
ClearHover();
|
||||||
|
entity_list.RefreshClientXTargets(this);
|
||||||
|
SendHPUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
//After they've respawned into the same zone, trigger EVENT_RESPAWN
|
||||||
|
parse->EventPlayer(EVENT_RESPAWN, this, static_cast<std::string>(itoa(Option)), is_rez ? 1 : 0);
|
||||||
|
|
||||||
|
//Pop Rez option from the respawn options list;
|
||||||
|
//easiest way to make sure it stays at the end and
|
||||||
|
//doesn't disrupt adding/removing scripted options
|
||||||
|
respawn_options.pop_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Heading to a different zone
|
||||||
if(isgrouped)
|
if(isgrouped)
|
||||||
{
|
{
|
||||||
Group *g = GetGroup();
|
Group *g = GetGroup();
|
||||||
@ -2129,17 +2181,16 @@ void Client::HandleRespawnFromHover(uint32 Option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Raid* r = entity_list.GetRaidByClient(this);
|
Raid* r = entity_list.GetRaidByClient(this);
|
||||||
|
|
||||||
if(r)
|
if(r)
|
||||||
r->MemberZoned(this);
|
r->MemberZoned(this);
|
||||||
|
|
||||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
m_pp.zone_id = chosen->zoneid;
|
||||||
m_pp.zoneInstance = 0;
|
m_pp.zoneInstance = 0;
|
||||||
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
|
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(chosen->zoneid));
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
|
||||||
GoToDeath();
|
MovePC(chosen->zoneid,chosen->x,chosen->y,chosen->z,chosen->heading,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
|||||||
"EVENT_CONNECT",
|
"EVENT_CONNECT",
|
||||||
"EVENT_ITEM_TICK",
|
"EVENT_ITEM_TICK",
|
||||||
"EVENT_DUEL_WIN",
|
"EVENT_DUEL_WIN",
|
||||||
"EVENT_DUEL_LOSE"
|
"EVENT_DUEL_LOSE",
|
||||||
|
"EVENT_RESPAWN"
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Zone* zone;
|
extern Zone* zone;
|
||||||
@ -818,6 +819,13 @@ void PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * d
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EVENT_RESPAWN:
|
||||||
|
{
|
||||||
|
ExportVar(packagename.c_str(), "respawn_option", data);
|
||||||
|
ExportVar(packagename.c_str(), "is_rez", extradata);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//nothing special about these events
|
//nothing special about these events
|
||||||
case EVENT_DEATH:
|
case EVENT_DEATH:
|
||||||
case EVENT_SPAWN:
|
case EVENT_SPAWN:
|
||||||
|
|||||||
@ -61,6 +61,7 @@ typedef enum {
|
|||||||
EVENT_ITEM_TICK,
|
EVENT_ITEM_TICK,
|
||||||
EVENT_DUEL_WIN,
|
EVENT_DUEL_WIN,
|
||||||
EVENT_DUEL_LOSE,
|
EVENT_DUEL_LOSE,
|
||||||
|
EVENT_RESPAWN, //PC respawning from hover without changing zones
|
||||||
|
|
||||||
_LargestEventID
|
_LargestEventID
|
||||||
} QuestEventID;
|
} QuestEventID;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user