Glowpaths/waypoints added
Fixed spell error messages for DoF client Fixed food/drinks for DoF client Changed items to allow archetypes to use an item if all the classes in the archetype are allowed to use it Added a ton of LUA functions to support various gameplay features Loot icon only added to corpse if the corpse has loot Class skills will now rise appropriately with level Fixed various bugs
This commit is contained in:
parent
cda936ad3f
commit
65109b0d5d
36 changed files with 1164 additions and 276 deletions
1
DB/updates/spells_update_sep_27_2020.sql
Normal file
1
DB/updates/spells_update_sep_27_2020.sql
Normal file
|
@ -0,0 +1 @@
|
|||
ALTER TABLE `spells` ADD COLUMN `fade_message_others` VARCHAR(255) NOT NULL DEFAULT '' AFTER `fade_message`;
|
|
@ -1135,15 +1135,19 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
}
|
||||
case COMMAND_RELOADSTRUCTS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Structs...");
|
||||
world.SetReloadingSubsystem("Structs");
|
||||
configReader.ReloadStructs();
|
||||
world.RemoveReloadingSubSystem("Structs");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
case COMMAND_RELOAD_QUESTS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Quests...");
|
||||
world.SetReloadingSubsystem("Quests");
|
||||
master_quest_list.Reload();
|
||||
client_list.ReloadQuests();
|
||||
zone_list.ReloadClientQuests();
|
||||
world.RemoveReloadingSubSystem("Quests");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
|
@ -1153,42 +1157,52 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
}
|
||||
case COMMAND_RELOAD_SPELLS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Spells...");
|
||||
world.SetReloadingSubsystem("Spells");
|
||||
zone_list.DeleteSpellProcess();
|
||||
master_spell_list.Reload();
|
||||
if (lua_interface)
|
||||
lua_interface->ReloadSpells();
|
||||
zone_list.LoadSpellProcess();
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
world.RemoveReloadingSubSystem("Spells");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
case COMMAND_RELOAD_GROUNDSPAWNS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Groundspawn Entries...");
|
||||
world.SetReloadingSubsystem("GroundSpawns");
|
||||
client->GetCurrentZone()->DeleteGroundSpawnItems();
|
||||
client->GetCurrentZone()->LoadGroundSpawnEntries();
|
||||
world.RemoveReloadingSubSystem("GroundSpawns");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
|
||||
case COMMAND_RELOAD_ZONESCRIPTS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Zone Scripts...");
|
||||
world.SetReloadingSubsystem("ZoneScripts");
|
||||
world.ResetZoneScripts();
|
||||
database.LoadZoneScriptData();
|
||||
if (lua_interface)
|
||||
lua_interface->DestroyZoneScripts();
|
||||
world.RemoveReloadingSubSystem("ZoneScripts");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
case COMMAND_RELOAD_ENTITYCOMMANDS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Entity Commands...");
|
||||
world.SetReloadingSubsystem("EntityCommands");
|
||||
client->GetCurrentZone()->ClearEntityCommands();
|
||||
database.LoadEntityCommands(client->GetCurrentZone());
|
||||
world.RemoveReloadingSubSystem("EntityCommands");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
case COMMAND_RELOAD_FACTIONS: {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Reloading Factions...");
|
||||
world.SetReloadingSubsystem("Factions");
|
||||
master_faction_list.Clear();
|
||||
database.LoadFactionList();
|
||||
world.RemoveReloadingSubSystem("Factions");
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Done!");
|
||||
break;
|
||||
}
|
||||
|
@ -1354,8 +1368,13 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
}
|
||||
else if (strcmp(sep->arg[0], "spellbook") == 0) {
|
||||
sint32 spell_id = atol(sep->arg[1]);
|
||||
int8 tier = atoi(sep->arg[2]);
|
||||
EQ2Packet* outapp = master_spell_list.GetSpellPacket(spell_id, tier, client, true, 0x2A);
|
||||
int32 tier = atoi(sep->arg[2]);
|
||||
if (tier > 255) {
|
||||
SpellBookEntry* ent = client->GetPlayer()->GetSpellBookSpell(spell_id);
|
||||
if (ent)
|
||||
tier = ent->tier;
|
||||
}
|
||||
EQ2Packet* outapp = master_spell_list.GetSpellPacket(spell_id, (int8)tier, client, true, 0x2A);
|
||||
if (outapp)
|
||||
client->QueuePacket(outapp);
|
||||
else
|
||||
|
@ -1386,7 +1405,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
LogWrite(COMMAND__DEBUG, 5, "Command", "Unknown Spell ID: %u", spell_id);
|
||||
int8 tier = client->GetPlayer()->GetSpellTier(spell_id);
|
||||
int8 type = 0;
|
||||
if (client->GetVersion() <= 283)
|
||||
if (client->GetVersion() <= 546)
|
||||
type = 1;
|
||||
EQ2Packet* outapp = master_spell_list.GetSpecialSpellPacket(spell_id, tier, client, true, type);
|
||||
if (outapp){
|
||||
|
@ -1910,8 +1929,6 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
|
|||
new_level = 255;
|
||||
|
||||
client->ChangeLevel(client->GetPlayer()->GetLevel(), new_level);
|
||||
client->GetPlayer()->SetXP(1);
|
||||
client->GetPlayer()->SetNeededXP();
|
||||
}
|
||||
}else
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /level {new_level}");
|
||||
|
@ -7746,6 +7763,12 @@ void Commands::Command_Toggle_AutoConsume(Client* client, Seperator* sep)
|
|||
{
|
||||
int8 slot = atoi(sep->arg[0]);
|
||||
int8 flag = atoi(sep->arg[1]);
|
||||
if (client->GetVersion() <= 283) {
|
||||
slot += 4;
|
||||
}
|
||||
else if (client->GetVersion() <= 546) {
|
||||
slot += 2;
|
||||
}
|
||||
if (slot == EQ2_FOOD_SLOT)
|
||||
{
|
||||
player->toggle_character_flag(CF_FOOD_AUTO_CONSUME);
|
||||
|
@ -8450,8 +8473,8 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
|
|||
}
|
||||
}
|
||||
else if (atoi(sep->arg[0]) == 5) {
|
||||
int16 offset = atoi(sep->arg[0]);
|
||||
int32 value1 = atol(sep->arg[1]);
|
||||
int16 offset = atoi(sep->arg[1]);
|
||||
int32 value1 = atol(sep->arg[2]);
|
||||
EQ2Packet* outapp = client->GetPlayer()->GetPlayerInfo()->serialize(client->GetVersion(), offset, value1);
|
||||
client->QueuePacket(outapp);
|
||||
}
|
||||
|
@ -8543,21 +8566,39 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
|
|||
client->QueuePacket(ret);
|
||||
}
|
||||
}
|
||||
else if (atoi(sep->arg[0]) == 9) {
|
||||
Spawn* spawn = client->GetPlayer()->GetTarget();
|
||||
if (spawn) {
|
||||
if (sep->IsSet(3)) {
|
||||
int32 amount = (int32)atoi(sep->arg[3]);
|
||||
spawn->SetActivityStatus(amount);
|
||||
}
|
||||
else if (atoi(sep->arg[0]) == 9) {
|
||||
PacketStruct* packet2 = configReader.getStruct("WS_DeathWindow", client->GetVersion());
|
||||
if (packet2) {
|
||||
packet2->setArrayLengthByName("location_count", 1);
|
||||
packet2->setArrayDataByName("location_ida", 1234);
|
||||
packet2->setArrayDataByName("unknown2a", 3);
|
||||
packet2->setArrayDataByName("zone_name", "Queen's Colony");
|
||||
packet2->setArrayDataByName("location_name", "Myrrin's Tower");
|
||||
packet2->setArrayDataByName("distance", 134);
|
||||
EQ2Packet* app = packet2->serialize();
|
||||
if (sep->IsSet(2)) {
|
||||
int8 amount = (int8)atoi(sep->arg[2]);
|
||||
spawn->SetLockedNoLoot(amount);
|
||||
}
|
||||
if (sep->IsSet(1)) {
|
||||
sint8 amount = (sint8)atoi(sep->arg[1]);
|
||||
spawn->AddIconValue(amount);
|
||||
int8 offset = atoi(sep->arg[1]);
|
||||
uchar* ptr2 = app->pBuffer;
|
||||
ptr2 += offset;
|
||||
if (sep->IsNumber(2)) {
|
||||
int32 value1 = atol(sep->arg[2]);
|
||||
if (value1 > 0xFFFF)
|
||||
memcpy(ptr2, (uchar*)&value1, 4);
|
||||
else if (value1 > 0xFF)
|
||||
memcpy(ptr2, (uchar*)&value1, 2);
|
||||
else
|
||||
memcpy(ptr2, (uchar*)&value1, 1);
|
||||
}
|
||||
else {
|
||||
int8 len = strlen(sep->arg[2]);
|
||||
memcpy(ptr2, (uchar*)&len, 1);
|
||||
ptr2 += 1;
|
||||
memcpy(ptr2, sep->arg[2], len);
|
||||
}
|
||||
}
|
||||
DumpPacket(app);
|
||||
client->QueuePacket(app);
|
||||
safe_delete(packet2);
|
||||
}
|
||||
}
|
||||
else if (atoi(sep->arg[0]) == 10) {
|
||||
|
@ -8609,34 +8650,44 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
|
|||
else if (atoi(sep->arg[0]) == 11) {
|
||||
PacketStruct* packet2 = configReader.getStruct("WS_QuestJournalReply", client->GetVersion());
|
||||
if (packet2) {
|
||||
packet2->setDataByName("quest_id", 5);
|
||||
packet2->setDataByName("quest_id", 524);
|
||||
packet2->setDataByName("player_crc", 2900677088);
|
||||
packet2->setDataByName("name", "Archetype Selection");
|
||||
packet2->setDataByName("description", "I have reported my profession to Garven Tralk");
|
||||
packet2->setDataByName("name", "Tasks aboard the Far Journey");
|
||||
packet2->setDataByName("description", "I completed all the tasks assigned to me by Captain Varlos aboard the Far Journey");
|
||||
packet2->setDataByName("type", "Hallmark");
|
||||
packet2->setDataByName("complete_header", "To complete this quest, I must do the following tasks:");
|
||||
packet2->setDataByName("day", 19);
|
||||
packet2->setDataByName("month", 6);
|
||||
packet2->setDataByName("year", 20);
|
||||
packet2->setDataByName("level", 2);
|
||||
packet2->setDataByName("encounter_level", 4);
|
||||
packet2->setDataByName("difficulty", 3);
|
||||
packet2->setDataByName("level", 1);
|
||||
packet2->setDataByName("encounter_level", 1);
|
||||
packet2->setDataByName("difficulty", 1);
|
||||
packet2->setDataByName("time_obtained", Timer::GetUnixTimeStamp());
|
||||
packet2->setDataByName("timer_start", Timer::GetUnixTimeStamp());
|
||||
packet2->setDataByName("timer_duration", 300);
|
||||
packet2->setDataByName("timer_running", 1);
|
||||
packet2->setArrayLengthByName("task_groups_completed", 0);
|
||||
packet2->setArrayLengthByName("num_task_groups", 1);
|
||||
packet2->setArrayDataByName("task_group", "I need to talk to Garven Tralk");
|
||||
packet2->setSubArrayLengthByName("num_tasks", 1);
|
||||
//packet2->setDataByName("timer_start", Timer::GetUnixTimeStamp());
|
||||
//packet2->setDataByName("timer_duration", 300);
|
||||
//packet2->setDataByName("timer_running", 1);
|
||||
packet2->setArrayLengthByName("task_groups_completed", 9);
|
||||
packet2->setArrayLengthByName("num_task_groups", 10);
|
||||
packet2->setArrayDataByName("task_group", "I spoke to Waulon as Captain Varlos had asked of me.");
|
||||
packet2->setArrayDataByName("task_group", "I found Waulon's hat in one of the boxes.", 1);
|
||||
packet2->setArrayDataByName("task_group", "I returned Waulon's hat.", 2);
|
||||
packet2->setArrayDataByName("task_group", "I have spoken to Ingrid.", 3);
|
||||
packet2->setArrayDataByName("task_group", "I purchased a Shard of Luclin.", 4);
|
||||
packet2->setArrayDataByName("task_group", "I gave the Shard of Luclin to Ingrid.", 5);
|
||||
packet2->setArrayDataByName("task_group", "I have spoken to Captain Varlos.", 6);
|
||||
packet2->setArrayDataByName("task_group", "I killed the rats that Captain Varlos requested.", 7);
|
||||
packet2->setArrayDataByName("task_group", "Captain Varlos has ordered you to kill the escaped goblin.", 8);
|
||||
packet2->setArrayDataByName("task_group", "I killed the escaped goblin.", 9);
|
||||
/*packet2->setSubArrayLengthByName("num_tasks", 1);
|
||||
packet2->setSubArrayDataByName("task", "I need to talk to Garven Tralk");
|
||||
packet2->setSubArrayLengthByName("num_updates", 1);
|
||||
packet2->setSubArrayDataByName("update_currentval", 0);
|
||||
packet2->setSubArrayDataByName("update_maxval", 1);
|
||||
packet2->setSubArrayDataByName("icon", 11);
|
||||
|
||||
*/
|
||||
packet2->setArrayDataByName("waypoint", 0xFFFFFFFF);
|
||||
packet2->setDataByName("journal_updated", 1);
|
||||
packet2->setDataByName("bullets", 1);
|
||||
EQ2Packet* app = packet2->serialize();
|
||||
if (sep->IsSet(2)) {
|
||||
int16 offset = atoi(sep->arg[1]);
|
||||
|
@ -8666,7 +8717,7 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
|
|||
else if (atoi(sep->arg[0]) == 12) {
|
||||
PacketStruct* packet2 = configReader.getStruct("WS_QuestJournalReply", client->GetVersion());
|
||||
if (packet2) {
|
||||
packet2->setDataByName("quest_id", 5);
|
||||
packet2->setDataByName("quest_id", 524);
|
||||
packet2->setDataByName("player_crc", 2900677088);
|
||||
packet2->setDataByName("name", "Archetype Selection");
|
||||
packet2->setDataByName("description", "I have reported my profession to Garven Tralk.");
|
||||
|
|
|
@ -499,6 +499,7 @@ void Entity::DoRegenUpdate(){
|
|||
if(GetPower() < GetTotalPower()){
|
||||
if(regen_power_rate == 0)
|
||||
regen_power_rate = level + (int)(level/10) + 1;
|
||||
cout << "regen_power_rate: " << regen_power_rate << endl;
|
||||
if((power + regen_power_rate) > GetTotalPower())
|
||||
SetPower(GetTotalPower());
|
||||
else
|
||||
|
@ -1376,7 +1377,11 @@ float Entity::GetSpeed() {
|
|||
ret += stats[ITEM_STAT_OFFENSIVESPEED];
|
||||
else if (stats.count(ITEM_STAT_SPEED) && stats.count(ITEM_STAT_MOUNTSPEED))
|
||||
ret += max(stats[ITEM_STAT_SPEED], stats[ITEM_STAT_MOUNTSPEED]);
|
||||
|
||||
else if (stats.count(ITEM_STAT_SPEED))
|
||||
ret += stats[ITEM_STAT_SPEED];
|
||||
else if (stats.count(ITEM_STAT_MOUNTSPEED))
|
||||
ret += stats[ITEM_STAT_MOUNTSPEED];
|
||||
|
||||
ret *= speed_multiplier;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -992,12 +992,69 @@ void Item::SetItem(Item* old_item){
|
|||
spell_tier = old_item->spell_tier;
|
||||
}
|
||||
|
||||
bool Item::CheckArchetypeAdvSubclass(int8 adventure_class, map<int8, int16>* adv_class_levels) {
|
||||
if (adventure_class > FIGHTER && adventure_class < ANIMALIST) {
|
||||
int8 check = adventure_class % 10;
|
||||
if (check == 2 || check == 5 || check == 8) {
|
||||
int64 adv_classes = 0;
|
||||
int16 level = 0;
|
||||
for (int i = adventure_class + 1; i < adventure_class + 3; i++) {
|
||||
if (adv_class_levels) { //need to match levels
|
||||
if (level == 0) {
|
||||
if (adv_class_levels->count(i) > 0)
|
||||
level = adv_class_levels->at(i);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
if (adv_class_levels->count(i) > 0 && adv_class_levels->at(i) != level)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
adv_classes = ((int64)2) << (i - 1);
|
||||
if (!(generic_info.adventure_classes & adv_classes))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Item::CheckArchetypeAdvClass(int8 adventure_class, map<int8, int16>* adv_class_levels) {
|
||||
if (adventure_class == 1 || adventure_class == 11 || adventure_class == 21 || adventure_class == 31) {
|
||||
//if the class is an archetype class and the subclasses have access, then allow
|
||||
if (CheckArchetypeAdvSubclass(adventure_class + 1, adv_class_levels) && CheckArchetypeAdvSubclass(adventure_class + 4, adv_class_levels) && CheckArchetypeAdvSubclass(adventure_class + 7, adv_class_levels)) {
|
||||
if (adv_class_levels) {
|
||||
int16 level = 0;
|
||||
for (int i = adventure_class + 1; i <= adventure_class + 7; i += 3) {
|
||||
if (adv_class_levels->count(i+1) == 0 || adv_class_levels->count(i + 2) == 0)
|
||||
return false;
|
||||
if(level == 0)
|
||||
level = adv_class_levels->at(i+1);
|
||||
if (adv_class_levels->at(i+1) != level) //already verified the classes, just need to verify the subclasses have the same levels
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (CheckArchetypeAdvSubclass(adventure_class, adv_class_levels)) {//check archetype subclass
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Item::CheckClass(int8 adventure_class, int8 tradeskill_class) {
|
||||
int64 adv_classes = ((int64)2) << (adventure_class - 1);
|
||||
int64 ts_classes = ((int64)2) << (tradeskill_class - 1);
|
||||
if( ((generic_info.adventure_classes & adv_classes) || generic_info.adventure_classes == 0) && ((generic_info.tradeskill_classes & ts_classes) || generic_info.tradeskill_classes == 0) )
|
||||
return true;
|
||||
return false;
|
||||
//check arechtype classes as last resort
|
||||
return CheckArchetypeAdvClass(adventure_class);
|
||||
}
|
||||
|
||||
bool Item::CheckLevel(int8 adventure_class, int8 tradeskill_class, int16 level) {
|
||||
|
@ -1720,7 +1777,7 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
|
|||
if(flags.length() > 0)
|
||||
packet->setSubstructDataByName("header_info", "flag_names", flags.c_str());
|
||||
}
|
||||
if(generic_info.adventure_classes > 0 || generic_info.tradeskill_classes > 0 || item_level_overrides.size() > 0){
|
||||
if (generic_info.adventure_classes > 0 || generic_info.tradeskill_classes > 0 || item_level_overrides.size() > 0) {
|
||||
//int64 classes = 0;
|
||||
int16 tmp_level = 0;
|
||||
map<int8, int16> adv_class_levels;
|
||||
|
@ -1736,18 +1793,18 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
|
|||
if (packet->GetVersion() >= 60000)
|
||||
temp += 2;
|
||||
|
||||
for(int32 i=0;i<=temp;i++){
|
||||
for (int32 i = 0; i <= temp; i++) {
|
||||
tmpVal = (int64)pow(2.0, (double)i);
|
||||
if((generic_info.adventure_classes & tmpVal)){
|
||||
if ((generic_info.adventure_classes & tmpVal)) {
|
||||
//classes += 2 << (i - 1);
|
||||
classes += tmpVal;
|
||||
tmp_level = GetOverrideLevel(i, 255);
|
||||
if(tmp_level == 0)
|
||||
if (tmp_level == 0)
|
||||
adv_class_levels[i] = generic_info.adventure_default_level;
|
||||
else
|
||||
adv_class_levels[i] = tmp_level;
|
||||
}
|
||||
if(tmpVal == 0) {
|
||||
if (tmpVal == 0) {
|
||||
if (packet->GetVersion() >= 60000)
|
||||
classes = 576379072454289112;
|
||||
else if (packet->GetVersion() >= 57048)
|
||||
|
@ -1758,27 +1815,73 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
|
|||
classes = 36024082983773912;
|
||||
}
|
||||
}
|
||||
for(int i=ALCHEMIST + 1 - ARTISAN ;i>=0;i--){
|
||||
for (int i = ALCHEMIST + 1 - ARTISAN; i >= 0; i--) {
|
||||
//tmpVal = 2 << i;
|
||||
tmpVal = (int64)pow(2.0, (double)i);
|
||||
if((generic_info.tradeskill_classes & tmpVal)){
|
||||
classes += pow(2, (i + ARTISAN ));
|
||||
if ((generic_info.tradeskill_classes & tmpVal)) {
|
||||
classes += pow(2, (i + ARTISAN));
|
||||
//classes += 2 << (i+ARTISAN-1);
|
||||
tmp_level = GetOverrideLevel(i, 255);
|
||||
if(tmp_level == 0)
|
||||
if (tmp_level == 0)
|
||||
tradeskill_class_levels[i] = generic_info.tradeskill_default_level;
|
||||
else
|
||||
tradeskill_class_levels[i] = tmp_level;
|
||||
}
|
||||
}
|
||||
bool simplified_display = false;
|
||||
if (client->GetVersion() <= 546) { //simplify display (if possible)
|
||||
map<int8, int16> new_adv_class_levels;
|
||||
for (int i = 1; i <= 31; i += 10) {
|
||||
bool add_archetype = CheckArchetypeAdvClass(i, &adv_class_levels);
|
||||
if (add_archetype) {
|
||||
new_adv_class_levels[i] = 0;
|
||||
}
|
||||
else {
|
||||
for (int x = 1; x <= 7; x += 3) {
|
||||
if (CheckArchetypeAdvSubclass(i+x, &adv_class_levels)) {
|
||||
new_adv_class_levels[i+x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (new_adv_class_levels.size() > 0) {
|
||||
simplified_display = true;
|
||||
int8 i = 0;
|
||||
for (itr = new_adv_class_levels.begin(); itr != new_adv_class_levels.end(); itr++) {
|
||||
i = itr->first;
|
||||
if ((i % 10) == 1) {
|
||||
int16 level = 0;
|
||||
for (int x = i; x < i+10; x++) {
|
||||
if (adv_class_levels.count(x) > 0) {
|
||||
if(level == 0)
|
||||
level = adv_class_levels.at(x);
|
||||
adv_class_levels.erase(x);
|
||||
}
|
||||
}
|
||||
adv_class_levels[i] = level;
|
||||
}
|
||||
else {
|
||||
int16 level = 0;
|
||||
for (int x = i+1; x < i + 3; x++) {
|
||||
if (adv_class_levels.count(x) > 0) {
|
||||
if (level == 0)
|
||||
level = adv_class_levels.at(x);
|
||||
adv_class_levels.erase(x);
|
||||
}
|
||||
}
|
||||
adv_class_levels[i] = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
packet->setSubstructArrayLengthByName("header_info", "class_count", adv_class_levels.size() + tradeskill_class_levels.size());
|
||||
int i = 0;
|
||||
for(itr = adv_class_levels.begin(); itr != adv_class_levels.end(); itr++, i++){
|
||||
for (itr = adv_class_levels.begin(); itr != adv_class_levels.end(); itr++, i++) {
|
||||
packet->setArrayDataByName("adventure_class", itr->first, i);
|
||||
packet->setArrayDataByName("tradeskill_class", 255, i);
|
||||
packet->setArrayDataByName("level", itr->second*10, i);
|
||||
packet->setArrayDataByName("level", itr->second * 10, i);
|
||||
}
|
||||
for(itr = tradeskill_class_levels.begin(); itr != tradeskill_class_levels.end(); itr++, i++){
|
||||
for (itr = tradeskill_class_levels.begin(); itr != tradeskill_class_levels.end(); itr++, i++) {
|
||||
packet->setArrayDataByName("adventure_class", 255, i);
|
||||
packet->setArrayDataByName("tradeskill_class", itr->first, i);
|
||||
packet->setArrayDataByName("level", itr->second, i);
|
||||
|
@ -1838,6 +1941,14 @@ void Item::serialize(PacketStruct* packet, bool show_name, Player* player, int16
|
|||
else if(slot == EQ2_DRINK_SLOT)
|
||||
slot = EQ2_ORIG_DRINK_SLOT;
|
||||
}
|
||||
else if (client->GetVersion() <= 546) {
|
||||
if (slot > EQ2_EARS_SLOT_1 && slot <= EQ2_WAIST_SLOT) //they added a second ear slot later, adjust for only 1 original slot
|
||||
slot -= 1;
|
||||
else if (slot == EQ2_FOOD_SLOT)
|
||||
slot = EQ2_DOF_FOOD_SLOT;
|
||||
else if (slot == EQ2_DRINK_SLOT)
|
||||
slot = EQ2_DOF_DRINK_SLOT;
|
||||
}
|
||||
packet->setArrayDataByName("slot", slot, i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ extern MasterItemList master_item_list;
|
|||
#define EQ2_BACK_SLOT 30
|
||||
#define EQ2_ORIG_FOOD_SLOT 18
|
||||
#define EQ2_ORIG_DRINK_SLOT 19
|
||||
#define EQ2_DOF_FOOD_SLOT 20
|
||||
#define EQ2_DOF_DRINK_SLOT 21
|
||||
|
||||
#define PRIMARY_SLOT 1
|
||||
#define SECONDARY_SLOT 2
|
||||
|
@ -99,6 +101,8 @@ extern MasterItemList master_item_list;
|
|||
#define BACK_SLOT 1073741824
|
||||
#define ORIG_FOOD_SLOT 524288
|
||||
#define ORIG_DRINK_SLOT 1048576
|
||||
#define DOF_FOOD_SLOT 1048576
|
||||
#define DOF_DRINK_SLOT 2097152
|
||||
|
||||
#define CLASSIC_EQ_MAX_BAG_SLOTS 20
|
||||
#define NUM_BANK_SLOTS 12
|
||||
|
@ -855,6 +859,8 @@ public:
|
|||
void AddLevelOverride(ItemLevelOverride* class_);
|
||||
bool CheckClassLevel(int8 adventure_class, int8 tradeskill_class, int16 level);
|
||||
bool CheckClass(int8 adventure_class, int8 tradeskill_class);
|
||||
bool CheckArchetypeAdvClass(int8 adventure_class, map<int8, int16>* adv_class_levels = 0);
|
||||
bool CheckArchetypeAdvSubclass(int8 adventure_class, map<int8, int16>* adv_class_levels = 0);
|
||||
bool CheckLevel(int8 adventure_class, int8 tradeskill_class, int16 level);
|
||||
void SetAppearance(int16 type, int8 red, int8 green, int8 blue, int8 highlight_red, int8 highlight_green, int8 highlight_blue);
|
||||
void SetAppearance(ItemAppearance* appearance);
|
||||
|
|
|
@ -337,6 +337,30 @@ int EQ2Emu_lua_ChangeHandIcon(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
//this function is used to force an update packet to be sent.
|
||||
//Useful if certain calculated things change after the player is sent the spawn packet, like quest flags or player has access to an object now
|
||||
int EQ2Emu_lua_SetVisualFlag(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
if (spawn) {
|
||||
spawn->vis_changed = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//this function is used to force an update packet to be sent.
|
||||
//Useful if certain calculated things change after the player is sent the spawn packet, like quest flags or player has access to an object now
|
||||
int EQ2Emu_lua_SetInfoFlag(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
if (spawn) {
|
||||
spawn->info_changed = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_SendStateCommand(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -3207,6 +3231,27 @@ int EQ2Emu_lua_AddQuestSelectableRewardItem(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_HasQuestRewardItem(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Quest* quest = lua_interface->GetQuest(state);
|
||||
if (quest) {
|
||||
int32 item_id = lua_interface->GetInt32Value(state, 2);
|
||||
vector<Item*>* items = quest->GetRewardItems();
|
||||
if (items) {
|
||||
vector<Item*>::iterator itr;
|
||||
for (itr = items->begin(); itr != items->end(); itr++) {
|
||||
if (*itr && (*itr)->details.item_id == item_id) {
|
||||
lua_interface->SetBooleanValue(state, true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lua_interface->SetBooleanValue(state, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddQuestRewardItem(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -3694,8 +3739,6 @@ int EQ2Emu_lua_GiveImmediateQuestReward(lua_State* state) {
|
|||
string factions_map_str = lua_interface->GetStringValue(state, 7);
|
||||
string text = lua_interface->GetStringValue(state, 8);
|
||||
int32 source_id = 0;
|
||||
if (quest)
|
||||
source_id = quest->GetQuestID();
|
||||
if (playerSpawn && playerSpawn->IsPlayer()) {
|
||||
Player* player = (Player*)playerSpawn;
|
||||
Client* client = player->GetZone()->GetClientBySpawn(player);
|
||||
|
@ -3710,7 +3753,7 @@ int EQ2Emu_lua_GiveImmediateQuestReward(lua_State* state) {
|
|||
Item* item = new Item(master_item_list.GetItem(itr->first));
|
||||
if (item) {
|
||||
if (itr->second > 0)
|
||||
item->stack_count = itr->second;
|
||||
item->details.count = itr->second;
|
||||
reward_items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
@ -3734,93 +3777,9 @@ int EQ2Emu_lua_GiveImmediateQuestReward(lua_State* state) {
|
|||
const char* reward_type = "Quest Reward!";
|
||||
if (!quest)
|
||||
reward_type = "Reward!";
|
||||
client->DisplayQuestRewards(0, coin, &reward_items, &selectable_reward_items, &faction_rewards, reward_type, status_points, text.c_str());
|
||||
client->DisplayQuestRewards(quest, coin, &reward_items, &selectable_reward_items, &faction_rewards, reward_type, status_points, text.c_str());
|
||||
}
|
||||
}
|
||||
/*PacketStruct* packet2 = configReader.getStruct("WS_QuestRewardPackMsg", client->GetVersion());
|
||||
if (packet2) {
|
||||
player->AddCoins(coin);
|
||||
client->PlaySound("coin_cha_ching");
|
||||
packet2->setSubstructDataByName("reward_data", "unknown1", 255);
|
||||
if(quest)
|
||||
packet2->setSubstructDataByName("reward_data", "reward", "Quest Reward!");
|
||||
else
|
||||
packet2->setSubstructDataByName("reward_data", "reward", "Reward!");
|
||||
packet2->setSubstructDataByName("reward_data", "coin", coin);
|
||||
if (player->GetGuild()) {
|
||||
player->GetInfoStruct()->status_points += status_points;
|
||||
packet2->setSubstructDataByName("reward_data", "status_points", status_points);
|
||||
}
|
||||
if (rewards_str.length() > 0) {
|
||||
map<unsigned int, unsigned short> rewards = ParseIntMap(rewards_str);
|
||||
vector<Item*> reward_items;
|
||||
map<unsigned int, unsigned short>::iterator itr;
|
||||
for (itr = rewards.begin(); itr != rewards.end(); itr++) {
|
||||
if (itr->first > 0) {
|
||||
Item* item = new Item(master_item_list.GetItem(itr->first));
|
||||
if (item) {
|
||||
if (itr->second > 0)
|
||||
item->stack_count = itr->second;
|
||||
reward_items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
packet2->setSubstructArrayLengthByName("reward_data", "num_rewards", reward_items.size());
|
||||
for (int i = 0; i < reward_items.size(); i++) {
|
||||
Item* item = reward_items[i];
|
||||
packet2->setArrayDataByName("reward_id", item->details.item_id, i);
|
||||
packet2->setItemArrayDataByName("item", item, client->GetPlayer(), i, 0, -1);
|
||||
player->AddPendingItemReward(item); //item reference will be deleted after the player accepts it
|
||||
}
|
||||
}
|
||||
if (select_rewards_str.length() > 0) {
|
||||
map<unsigned int, unsigned short> rewards = ParseIntMap(select_rewards_str);
|
||||
vector<Item*> reward_items;
|
||||
map<unsigned int, unsigned short>::iterator itr;
|
||||
for (itr = rewards.begin(); itr != rewards.end(); itr++) {
|
||||
if (itr->first > 0) {
|
||||
Item* item = new Item(master_item_list.GetItem(itr->first));
|
||||
if (item) {
|
||||
if (itr->second > 0)
|
||||
item->stack_count = itr->second;
|
||||
reward_items.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
packet2->setSubstructArrayLengthByName("reward_data", "num_select_rewards", reward_items.size());
|
||||
for (int i = 0; i < reward_items.size(); i++) {
|
||||
Item* item = reward_items[i];
|
||||
packet2->setArrayDataByName("select_reward_id", item->details.item_id, i);
|
||||
packet2->setItemArrayDataByName("select_item", item, client->GetPlayer(), i, 0, -1);
|
||||
player->AddPendingSelectableItemReward(source_id, item); //item reference will be deleted after the player selects one
|
||||
}
|
||||
}
|
||||
if (factions_map_str.length() > 0) {
|
||||
map<unsigned int, signed int> faction_rewards = ParseSInt32Map(factions_map_str);
|
||||
map<unsigned int, signed int>::iterator itr;
|
||||
map<Faction*, signed int> factions;
|
||||
for (itr = faction_rewards.begin(); itr != faction_rewards.end(); itr++) {
|
||||
Faction* faction = master_faction_list.GetFaction(itr->first);
|
||||
if (faction)
|
||||
factions[faction] = itr->second;
|
||||
}
|
||||
packet2->setSubstructArrayLengthByName("reward_data", "num_factions", factions.size());
|
||||
map<Faction*, signed int>::iterator faction_itr;
|
||||
int8 i = 0;
|
||||
for (faction_itr = factions.begin(); faction_itr != factions.end(); faction_itr++) {
|
||||
packet2->setArrayDataByName("faction_name", faction_itr->first->name.c_str(), i);
|
||||
sint32 amount = faction_itr->second;
|
||||
packet2->setArrayDataByName("amount", amount, i);
|
||||
if (amount > 0)
|
||||
player->GetFactions()->IncreaseFaction(faction_itr->first->id, amount);
|
||||
else
|
||||
player->GetFactions()->DecreaseFaction(faction_itr->first->id, (amount * -1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
client->QueuePacket(packet2->serialize());
|
||||
safe_delete(packet2);
|
||||
}*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4099,22 +4058,41 @@ int EQ2Emu_lua_AddPrimaryEntityCommand(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_HasSpell(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
int32 spellid = lua_interface->GetInt32Value(state, 2);
|
||||
int16 tier = lua_interface->GetInt16Value(state, 3);
|
||||
if (player && player->IsPlayer()) {
|
||||
lua_interface->SetBooleanValue(state, ((Player*)player)->HasSpell(spellid, tier, true));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddSpellBookEntry(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
int32 spellid = lua_interface->GetInt32Value(state, 2);
|
||||
int16 tier = lua_interface->GetInt16Value(state, 3);
|
||||
int8 num_args = (int8)lua_interface->GetNumberOfArgs(state);
|
||||
bool add_silently = lua_interface->GetBooleanValue(state, 4);
|
||||
bool add_to_hotbar = true;
|
||||
if (num_args > 4) {
|
||||
add_to_hotbar = lua_interface->GetBooleanValue(state, 5);
|
||||
}
|
||||
Spell* spell = master_spell_list.GetSpell(spellid, tier);
|
||||
if (player && spell && player->IsPlayer()) {
|
||||
Client* client = player->GetZone()->GetClientBySpawn(player);
|
||||
Client* client = player->GetClient();
|
||||
if (client) {
|
||||
if (!client->GetPlayer()->HasSpell(spellid, tier - 1, true))
|
||||
{
|
||||
Spell* spell = master_spell_list.GetSpell(spellid, tier);
|
||||
client->GetPlayer()->AddSpellBookEntry(spellid, 1, client->GetPlayer()->GetFreeSpellBookSlot(spell->GetSpellData()->spell_book_type), spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
client->GetPlayer()->UnlockSpell(spell);
|
||||
client->SendSpellUpdate(spell);
|
||||
client->SendSpellUpdate(spell, add_silently, add_to_hotbar);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4123,7 +4101,7 @@ int EQ2Emu_lua_AddSpellBookEntry(lua_State* state) {
|
|||
client->GetPlayer()->RemoveSpellBookEntry(spell->GetSpellID());
|
||||
client->GetPlayer()->AddSpellBookEntry(spell->GetSpellID(), spell->GetSpellTier(), old_slot, spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
client->GetPlayer()->UnlockSpell(spell);
|
||||
client->SendSpellUpdate(spell);
|
||||
client->SendSpellUpdate(spell, add_silently, add_to_hotbar);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5423,6 +5401,51 @@ int EQ2Emu_lua_GetArchetypeName(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_SendWaypoints(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
if (player && player->IsPlayer()) {
|
||||
Client* client = player->GetClient();
|
||||
if (client)
|
||||
client->SendWaypoints();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddWaypoint(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
string name = lua_interface->GetStringValue(state, 2);
|
||||
int32 type = lua_interface->GetInt32Value(state, 3);
|
||||
if (type == 0)
|
||||
type = 2;
|
||||
if (name.length() > 0) {
|
||||
if (player && player->IsPlayer()) {
|
||||
Client* client = player->GetClient();
|
||||
if (client)
|
||||
client->AddWaypoint(name, type);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_RemoveWaypoint(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
string name = lua_interface->GetStringValue(state, 2);
|
||||
if (name.length() > 0) {
|
||||
if (player && player->IsPlayer()) {
|
||||
Client* client = player->GetClient();
|
||||
if (client)
|
||||
client->RemoveWaypoint(name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddWard(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -7063,6 +7086,119 @@ int EQ2Emu_lua_SetSkillValue(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_HasSkill(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player = lua_interface->GetSpawn(state);
|
||||
int32 skill_id = lua_interface->GetInt32Value(state, 2);
|
||||
if (skill_id > 0 && player && player->IsPlayer()) {
|
||||
lua_interface->SetBooleanValue(state, ((Player*)player)->skill_list.HasSkill(skill_id));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_AddSkill(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player_spawn = lua_interface->GetSpawn(state);
|
||||
int32 skill_id = lua_interface->GetInt32Value(state, 2);
|
||||
int16 current_val = lua_interface->GetInt16Value(state, 3);
|
||||
int16 max_val = lua_interface->GetInt16Value(state, 4);
|
||||
bool more_to_add = lua_interface->GetBooleanValue(state, 5);
|
||||
if (skill_id > 0 && current_val > 0 && max_val > 0) {
|
||||
if (player_spawn && player_spawn->IsPlayer()) {
|
||||
Player* player = (Player*)player_spawn;
|
||||
bool added = false;
|
||||
if (!player->skill_list.HasSkill(skill_id)) {
|
||||
player->AddSkill(skill_id, current_val, max_val, true);
|
||||
added = true;
|
||||
}
|
||||
if (!more_to_add) { //need to send update regardless, even if THIS skill wasn't added, otherwise if you have a list and the last item wasn't added but the previous ones were, it wouldn't send the update
|
||||
Client* client = player->GetClient();
|
||||
if (client) {
|
||||
EQ2Packet* packet = player->GetSkills()->GetSkillPacket(client->GetVersion());
|
||||
if (packet)
|
||||
client->QueuePacket(packet);
|
||||
}
|
||||
}
|
||||
if (added) {
|
||||
lua_interface->SetBooleanValue(state, true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA AddSkill command error: Given spawn is not a player", lua_interface->GetScriptName(state));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA AddSkill command error: Required parameters not set", lua_interface->GetScriptName(state));
|
||||
}
|
||||
lua_interface->SetBooleanValue(state, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_RemoveSkill(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player_spawn = lua_interface->GetSpawn(state);
|
||||
int32 skill_id = lua_interface->GetInt32Value(state, 2);
|
||||
bool more_to_remove = lua_interface->GetBooleanValue(state, 3);
|
||||
if (skill_id > 0) {
|
||||
if (player_spawn && player_spawn->IsPlayer()) {
|
||||
Player* player = (Player*)player_spawn;
|
||||
if (player->skill_list.HasSkill(skill_id)) {
|
||||
player->RemovePlayerSkill(skill_id);
|
||||
if (!more_to_remove) {
|
||||
Client* client = player->GetClient();
|
||||
if (client) {
|
||||
EQ2Packet* packet = player->GetSkills()->GetSkillPacket(client->GetVersion());
|
||||
if (packet)
|
||||
client->QueuePacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA RemoveSkill command error: Given spawn is not a player", lua_interface->GetScriptName(state));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA RemoveSkill command error: skill_id not set", lua_interface->GetScriptName(state));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_IncreaseSkillCapsByType(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
Spawn* player_spawn = lua_interface->GetSpawn(state);
|
||||
int8 skill_type = lua_interface->GetInt8Value(state, 2);
|
||||
int16 amount = lua_interface->GetInt8Value(state, 3);
|
||||
bool more_to_increase = lua_interface->GetBooleanValue(state, 4);
|
||||
if (amount > 0 && skill_type < 100) {
|
||||
if (player_spawn && player_spawn->IsPlayer()) {
|
||||
Player* player = (Player*)player_spawn;
|
||||
player->skill_list.IncreaseSkillCapsByType(skill_type, amount);
|
||||
if (!more_to_increase) {
|
||||
Client* client = player->GetClient();
|
||||
if (client) {
|
||||
EQ2Packet* packet = player->GetSkills()->GetSkillPacket(client->GetVersion());
|
||||
if (packet)
|
||||
client->QueuePacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA IncreaseSkillCapsByType command error: Given spawn is not a player", lua_interface->GetScriptName(state));
|
||||
}
|
||||
}
|
||||
else {
|
||||
lua_interface->LogError("%s: LUA IncreaseSkillCapsByType command error: Invalid parameters", lua_interface->GetScriptName(state));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EQ2Emu_lua_GetSkill(lua_State* state) {
|
||||
if (!lua_interface)
|
||||
return 0;
|
||||
|
@ -9218,9 +9354,6 @@ int EQ2Emu_lua_SetPlayerLevel(lua_State* state) {
|
|||
}
|
||||
|
||||
client->ChangeLevel(client->GetPlayer()->GetLevel(), level);
|
||||
client->GetPlayer()->SetXP(1);
|
||||
client->GetPlayer()->SetNeededXP();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9977,7 +10110,7 @@ int EQ2Emu_lua_InstructionWindow(lua_State* state) {
|
|||
lua_interface->LogError("LUA InstructionWindow command error: could not find client");
|
||||
return 0;
|
||||
}
|
||||
if (text.length() == 0 || task1.length() == 0 || signal.length() == 0) {
|
||||
if (text.length() == 0) {
|
||||
lua_interface->LogError("LUA InstructionWindow required parameters not given");
|
||||
return 0;
|
||||
}
|
||||
|
@ -10458,16 +10591,16 @@ int EQ2Emu_lua_GetAlignment(lua_State* state) {
|
|||
Spawn* spawn = lua_interface->GetSpawn(state);
|
||||
|
||||
if (!spawn) {
|
||||
lua_interface->LogError("%s: LUA SetAlignment command error: spawn is not valid", lua_interface->GetScriptName(state));
|
||||
lua_interface->LogError("%s: LUA GetAlignment command error: spawn is not valid", lua_interface->GetScriptName(state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!spawn->IsEntity()) {
|
||||
lua_interface->LogError("%s: LUA SetAlignment command error: spawn is not an entity", lua_interface->GetScriptName(state));
|
||||
lua_interface->LogError("%s: LUA GetAlignment command error: spawn is not an entity", lua_interface->GetScriptName(state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_interface->SetInt32Value(state, ((Entity*)spawn)->GetAlignment());
|
||||
lua_interface->SetSInt32Value(state, ((Entity*)spawn)->GetAlignment());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,8 @@ int EQ2Emu_lua_SetRequiredQuest(lua_State* state);
|
|||
int EQ2Emu_lua_SetRequiredHistory(lua_State* state);
|
||||
int EQ2Emu_lua_Despawn(lua_State* state);
|
||||
int EQ2Emu_lua_ChangeHandIcon(lua_State* state);
|
||||
int EQ2Emu_lua_SetVisualFlag(lua_State* state);
|
||||
int EQ2Emu_lua_SetInfoFlag(lua_State* state);
|
||||
int EQ2Emu_lua_AddHate(lua_State* state);
|
||||
int EQ2Emu_lua_GetZone(lua_State* state);
|
||||
int EQ2Emu_lua_GetZoneName(lua_State* state);
|
||||
|
@ -202,6 +204,7 @@ int EQ2Emu_lua_SetServerControlFlag(lua_State* state);
|
|||
int EQ2Emu_lua_ToggleTracking(lua_State* state);
|
||||
int EQ2Emu_lua_AddPrimaryEntityCommand(lua_State* state);
|
||||
int EQ2Emu_lua_AddSpellBookEntry(lua_State* state);
|
||||
int EQ2Emu_lua_HasSpell(lua_State* state);
|
||||
int EQ2Emu_lua_Attack(lua_State* state);
|
||||
int EQ2Emu_lua_ApplySpellVisual(lua_State* state);
|
||||
int EQ2Emu_lua_Interrupt(lua_State* state);
|
||||
|
@ -232,6 +235,7 @@ int EQ2Emu_lua_AddQuestPrereqRace(lua_State* state);
|
|||
int EQ2Emu_lua_AddQuestPrereqModelType(lua_State* state);
|
||||
int EQ2Emu_lua_AddQuestPrereqTradeskillLevel(lua_State* state);
|
||||
int EQ2Emu_lua_AddQuestPrereqTradeskillClass(lua_State* state);
|
||||
int EQ2Emu_lua_HasQuestRewardItem(lua_State* state);
|
||||
int EQ2Emu_lua_AddQuestRewardItem(lua_State* state);
|
||||
int EQ2Emu_lua_AddQuestSelectableRewardItem(lua_State* state);
|
||||
int EQ2Emu_lua_AddQuestRewardCoin(lua_State* state);
|
||||
|
@ -311,6 +315,11 @@ int EQ2Emu_lua_GetTempVariable(lua_State* state);
|
|||
int EQ2Emu_lua_GiveQuestItem(lua_State*state);
|
||||
int EQ2Emu_lua_SetQuestRepeatable(lua_State* state);
|
||||
|
||||
|
||||
int EQ2Emu_lua_AddWaypoint(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveWaypoint(lua_State* state);
|
||||
int EQ2Emu_lua_SendWaypoints(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_AddWard(lua_State* state);
|
||||
int EQ2Emu_lua_AddToWard(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveWard(lua_State* state);
|
||||
|
@ -355,6 +364,10 @@ int EQ2Emu_lua_SetSkillMaxValue(lua_State* state);
|
|||
int EQ2Emu_lua_SetSkillValue(lua_State* state);
|
||||
int EQ2Emu_lua_GetSkill(lua_State* state);
|
||||
int EQ2Emu_lua_GetSkillIDByName(lua_State* state);
|
||||
int EQ2Emu_lua_HasSkill(lua_State* state);
|
||||
int EQ2Emu_lua_AddSkill(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveSkill(lua_State* state);
|
||||
int EQ2Emu_lua_IncreaseSkillCapsByType(lua_State* state);
|
||||
|
||||
int EQ2Emu_lua_AddProc(lua_State* state);
|
||||
int EQ2Emu_lua_RemoveProc(lua_State* state);
|
||||
|
|
|
@ -123,6 +123,10 @@ LuaInterface::~LuaInterface() {
|
|||
safe_delete(spell_delete_timer);
|
||||
}
|
||||
|
||||
int LuaInterface::GetNumberOfArgs(lua_State* state) {
|
||||
return lua_gettop(state);
|
||||
}
|
||||
|
||||
void LuaInterface::Process() {
|
||||
if(shutting_down)
|
||||
return;
|
||||
|
@ -753,6 +757,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "Attack", EQ2Emu_lua_Attack);
|
||||
lua_register(state, "ApplySpellVisual", EQ2Emu_lua_ApplySpellVisual);
|
||||
|
||||
|
||||
lua_register(state, "IsPlayer", EQ2Emu_lua_IsPlayer);
|
||||
lua_register(state, "FaceTarget", EQ2Emu_lua_FaceTarget);
|
||||
lua_register(state, "MoveToLocation", EQ2Emu_lua_MoveToLocation);
|
||||
|
@ -831,6 +836,8 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "KillSpawnByDistance", EQ2Emu_lua_KillSpawnByDistance);
|
||||
lua_register(state, "Despawn", EQ2Emu_lua_Despawn);
|
||||
lua_register(state, "ChangeHandIcon", EQ2Emu_lua_ChangeHandIcon);
|
||||
lua_register(state, "SetVisualFlag", EQ2Emu_lua_SetVisualFlag);
|
||||
lua_register(state, "SetInfoFlag", EQ2Emu_lua_SetInfoFlag);
|
||||
lua_register(state, "IsBindAllowed", EQ2Emu_lua_IsBindAllowed);
|
||||
lua_register(state, "IsGateAllowed", EQ2Emu_lua_IsGateAllowed);
|
||||
lua_register(state, "Bind", EQ2Emu_lua_Bind);
|
||||
|
@ -841,6 +848,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "ToggleTracking", EQ2Emu_lua_ToggleTracking);
|
||||
lua_register(state, "AddPrimaryEntityCommand", EQ2Emu_lua_AddPrimaryEntityCommand);
|
||||
lua_register(state, "AddSpellBookEntry", EQ2Emu_lua_AddSpellBookEntry);
|
||||
lua_register(state, "HasSpell", EQ2Emu_lua_HasSpell);
|
||||
lua_register(state, "Interrupt", EQ2Emu_lua_Interrupt);
|
||||
lua_register(state, "Stealth", EQ2Emu_lua_Stealth);
|
||||
lua_register(state, "IsInvis", EQ2Emu_lua_IsInvis);
|
||||
|
@ -868,6 +876,7 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "AddQuestPrereqTradeskillLevel", EQ2Emu_lua_AddQuestPrereqTradeskillLevel);
|
||||
lua_register(state, "AddQuestPrereqTradeskillClass", EQ2Emu_lua_AddQuestPrereqTradeskillClass);
|
||||
lua_register(state, "AddQuestSelectableRewardItem", EQ2Emu_lua_AddQuestSelectableRewardItem);
|
||||
lua_register(state, "HasQuestRewardItem", EQ2Emu_lua_HasQuestRewardItem);
|
||||
lua_register(state, "AddQuestRewardItem", EQ2Emu_lua_AddQuestRewardItem);
|
||||
lua_register(state, "AddQuestRewardCoin", EQ2Emu_lua_AddQuestRewardCoin);
|
||||
lua_register(state, "AddQuestRewardFaction", EQ2Emu_lua_AddQuestRewardFaction);
|
||||
|
@ -943,6 +952,10 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "GiveQuestItem", EQ2Emu_lua_GiveQuestItem);
|
||||
lua_register(state, "SetQuestRepeatable", EQ2Emu_lua_SetQuestRepeatable);
|
||||
|
||||
lua_register(state, "AddWaypoint", EQ2Emu_lua_AddWaypoint);
|
||||
lua_register(state, "RemoveWaypoint", EQ2Emu_lua_RemoveWaypoint);
|
||||
lua_register(state, "SendWaypoints", EQ2Emu_lua_SendWaypoints);
|
||||
|
||||
lua_register(state, "AddWard", EQ2Emu_lua_AddWard);
|
||||
lua_register(state, "AddToWard", EQ2Emu_lua_AddToWard);
|
||||
lua_register(state, "RemoveWard", EQ2Emu_lua_RemoveWard);
|
||||
|
@ -985,6 +998,10 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
|
|||
lua_register(state, "SetSkillValue", EQ2Emu_lua_SetSkillValue);
|
||||
lua_register(state, "GetSkill", EQ2Emu_lua_GetSkill);
|
||||
lua_register(state, "GetSkillIDByName", EQ2Emu_lua_GetSkillIDByName);
|
||||
lua_register(state, "HasSkill", EQ2Emu_lua_HasSkill);
|
||||
lua_register(state, "AddSkill", EQ2Emu_lua_AddSkill);
|
||||
lua_register(state, "IncreaseSkillCapsByType", EQ2Emu_lua_IncreaseSkillCapsByType);
|
||||
lua_register(state, "RemoveSkill", EQ2Emu_lua_RemoveSkill);
|
||||
lua_register(state, "AddProc", EQ2Emu_lua_AddProc);
|
||||
lua_register(state, "RemoveProc", EQ2Emu_lua_RemoveProc);
|
||||
lua_register(state, "Knockback", EQ2Emu_lua_Knockback);
|
||||
|
|
|
@ -179,6 +179,7 @@ class LuaInterface {
|
|||
public:
|
||||
LuaInterface();
|
||||
~LuaInterface();
|
||||
int GetNumberOfArgs(lua_State* state);
|
||||
bool LoadLuaSpell(const char* name);
|
||||
bool LoadLuaSpell(string name);
|
||||
bool LoadItemScript(string name);
|
||||
|
|
|
@ -228,14 +228,14 @@ void NPC::InCombat(bool val){
|
|||
in_combat = val;
|
||||
if(val){
|
||||
LogWrite(NPC__DEBUG, 3, "NPC", "'%s' engaged in combat with '%s'", this->GetName(), ( GetTarget() ) ? GetTarget()->GetName() : "Unknown" );
|
||||
SetLockedNoLoot(3);
|
||||
SetLockedNoLoot(ENCOUNTER_STATE_LOCKED);
|
||||
AddIconValue(64);
|
||||
// In combat so lets set the NPC's speed to its max speed
|
||||
if (GetMaxSpeed() > 0)
|
||||
SetSpeed(GetMaxSpeed());
|
||||
}
|
||||
else{
|
||||
SetLockedNoLoot(1);
|
||||
SetLockedNoLoot(ENCOUNTER_STATE_AVAILABLE);
|
||||
RemoveIconValue(64);
|
||||
if (GetHP() > 0){
|
||||
SetTempActionState(-1); //re-enable action states on exiting combat
|
||||
|
@ -258,7 +258,7 @@ void NPC::InCombat(bool val){
|
|||
}
|
||||
|
||||
bool NPC::HandleUse(Client* client, string type){
|
||||
if(!client || type.length() == 0 || appearance.show_command_icon == 0)
|
||||
if(!client || type.length() == 0 || (appearance.show_command_icon == 0 && appearance.display_hand_icon == 0))
|
||||
return false;
|
||||
EntityCommand* entity_command = FindEntityCommand(type);
|
||||
if (entity_command) {
|
||||
|
|
|
@ -1330,6 +1330,8 @@ EQ2Packet* PlayerInfo::serialize(int16 version, int16 modifyPos, int32 modifyVal
|
|||
packet->setSubstructDataByName("spell_effects", "expire_timestamp", expireTimestamp, i, 0);
|
||||
packet->setSubstructDataByName("spell_effects", "icon", info_struct->spell_effects[i].icon, i, 0);
|
||||
packet->setSubstructDataByName("spell_effects", "icon_type", info_struct->spell_effects[i].icon_backdrop, i, 0);
|
||||
if(info_struct->spell_effects[i].spell && info_struct->spell_effects[i].spell->spell && info_struct->spell_effects[i].spell->spell->GetSpellData()->friendly_spell == 1)
|
||||
packet->setSubstructDataByName("spell_effects", "cancellable", 1, i);
|
||||
}
|
||||
player->GetMaintainedMutex()->releasereadlock(__FUNCTION__, __LINE__);
|
||||
player->GetSpellEffectMutex()->releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
@ -1682,6 +1684,14 @@ int8 Player::ConvertSlotToClient(int8 slot, int16 version) {
|
|||
else if (slot > EQ2_EARS_SLOT_1 && slot <= EQ2_WAIST_SLOT)
|
||||
slot -= 1;
|
||||
}
|
||||
else if (version <= 546) {
|
||||
if (slot == EQ2_FOOD_SLOT)
|
||||
slot = EQ2_DOF_FOOD_SLOT;
|
||||
else if (slot == EQ2_DRINK_SLOT)
|
||||
slot = EQ2_DOF_DRINK_SLOT;
|
||||
else if (slot > EQ2_EARS_SLOT_1 && slot <= EQ2_WAIST_SLOT)
|
||||
slot -= 1;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
@ -1694,6 +1704,14 @@ int8 Player::ConvertSlotFromClient(int8 slot, int16 version) {
|
|||
else if (slot > EQ2_EARS_SLOT_1 && slot <= EQ2_WAIST_SLOT)
|
||||
slot += 1;
|
||||
}
|
||||
else if (version <= 546) {
|
||||
if (slot == EQ2_DOF_FOOD_SLOT)
|
||||
slot = EQ2_FOOD_SLOT;
|
||||
else if (slot == EQ2_DOF_DRINK_SLOT)
|
||||
slot = EQ2_DRINK_SLOT;
|
||||
else if (slot > EQ2_EARS_SLOT_1 && slot <= EQ2_WAIST_SLOT)
|
||||
slot += 1;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
@ -2197,7 +2215,7 @@ EQ2Packet* Player::GetQuickbarPacket(int16 version){
|
|||
|
||||
void Player::AddSpellBookEntry(int32 spell_id, int8 tier, sint32 slot, int32 type, int32 timer, bool save_needed){
|
||||
SpellBookEntry* spell = new SpellBookEntry;
|
||||
spell->status = 161;
|
||||
spell->status = 169;
|
||||
spell->slot = slot;
|
||||
spell->spell_id = spell_id;
|
||||
spell->type = type;
|
||||
|
@ -2442,13 +2460,21 @@ int8 Player::GetSpellSlot(int32 spell_id){
|
|||
|
||||
void Player::AddSkill(int32 skill_id, int16 current_val, int16 max_val, bool save_needed){
|
||||
Skill* master_skill = master_skill_list.GetSkill(skill_id);
|
||||
Skill* skill = new Skill(master_skill);
|
||||
skill->current_val = current_val;
|
||||
skill->previous_val = current_val;
|
||||
skill->max_val = max_val;
|
||||
if(save_needed)
|
||||
skill->save_needed = true;
|
||||
skill_list.AddSkill(skill);
|
||||
if (master_skill) {
|
||||
Skill* skill = new Skill(master_skill);
|
||||
skill->current_val = current_val;
|
||||
skill->previous_val = current_val;
|
||||
skill->max_val = max_val;
|
||||
if (save_needed)
|
||||
skill->save_needed = true;
|
||||
skill_list.AddSkill(skill);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::RemovePlayerSkill(int32 skill_id, bool save) {
|
||||
Skill* skill = skill_list.GetSkill(skill_id);
|
||||
if (skill)
|
||||
RemoveSkillFromDB(skill, save);
|
||||
}
|
||||
|
||||
void Player::RemoveSkillFromDB(Skill* skill, bool save) {
|
||||
|
@ -2501,18 +2527,20 @@ void Player::LockAllSpells() {
|
|||
MSpellsBook.writelock(__FUNCTION__, __LINE__);
|
||||
for (itr = spells.begin(); itr != spells.end(); itr++) {
|
||||
if ((*itr)->type != SPELL_BOOK_TYPE_TRADESKILL)
|
||||
AddSpellStatus((*itr), SPELL_STATUS_LOCK, false);
|
||||
RemoveSpellStatus((*itr), SPELL_STATUS_LOCK, false);
|
||||
}
|
||||
|
||||
MSpellsBook.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
void Player::UnlockAllSpells(bool modify_recast) {
|
||||
void Player::UnlockAllSpells(bool modify_recast, Spell* exception) {
|
||||
vector<SpellBookEntry*>::iterator itr;
|
||||
|
||||
int32 exception_spell_id = 0;
|
||||
if (exception)
|
||||
exception_spell_id = exception->GetSpellID();
|
||||
MSpellsBook.writelock(__FUNCTION__, __LINE__);
|
||||
for (itr = spells.begin(); itr != spells.end(); itr++) {
|
||||
if ((*itr)->type != SPELL_BOOK_TYPE_TRADESKILL)
|
||||
if ((*itr)->spell_id != exception_spell_id && (*itr)->type != SPELL_BOOK_TYPE_TRADESKILL)
|
||||
AddSpellStatus((*itr), SPELL_STATUS_LOCK, modify_recast);
|
||||
}
|
||||
|
||||
|
@ -2532,8 +2560,10 @@ void Player::LockSpell(Spell* spell, int16 recast) {
|
|||
}
|
||||
|
||||
void Player::UnlockSpell(Spell* spell) {
|
||||
if (spell->GetStayLocked())
|
||||
return;
|
||||
vector<SpellBookEntry*>::iterator itr;
|
||||
SpellBookEntry* spell2;
|
||||
SpellBookEntry* spell2;
|
||||
MSpellsBook.writelock(__FUNCTION__, __LINE__);
|
||||
for (itr = spells.begin(); itr != spells.end(); itr++) {
|
||||
spell2 = *itr;
|
||||
|
@ -2612,24 +2642,27 @@ void Player::ModifySpellStatus(SpellBookEntry* spell, sint16 value, bool modify_
|
|||
spell->recast = recast;
|
||||
spell->recast_available = Timer::GetCurrentTime2() + (recast * 100);
|
||||
}
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4)
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4) {
|
||||
spell->status += value; // use set/remove spell status now
|
||||
}
|
||||
}
|
||||
void Player::AddSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast, int16 recast) {
|
||||
if (modify_recast) {
|
||||
spell->recast = recast;
|
||||
spell->recast_available = Timer::GetCurrentTime2() + (recast * 100);
|
||||
}
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4)
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4) {
|
||||
spell->status = spell->status | value;
|
||||
}
|
||||
}
|
||||
void Player::RemoveSpellStatus(SpellBookEntry* spell, sint16 value, bool modify_recast, int16 recast) {
|
||||
if (modify_recast) {
|
||||
spell->recast = recast;
|
||||
spell->recast_available = Timer::GetCurrentTime2() + (recast * 100);
|
||||
}
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4)
|
||||
if (modify_recast || spell->recast_available <= Timer::GetCurrentTime2() || value == 4) {
|
||||
spell->status = spell->status & ~value;
|
||||
}
|
||||
|
||||
}
|
||||
void Player::SetSpellStatus(Spell* spell, int8 status){
|
||||
|
@ -2790,9 +2823,11 @@ EQ2Packet* Player::GetSpellBookUpdatePacket(int16 version) {
|
|||
if (spell_entry->spell_id == 0)
|
||||
continue;
|
||||
spell = master_spell_list.GetSpell(spell_entry->spell_id, spell_entry->tier);
|
||||
if (spell) {
|
||||
if (spell_entry->recast_available == 0 || Timer::GetCurrentTime2() > spell_entry->recast_available)
|
||||
if (spell) {
|
||||
if (spell_entry->recast_available == 0 || Timer::GetCurrentTime2() > spell_entry->recast_available) {
|
||||
packet->setSubstructArrayDataByName("spells", "available", 1, 0, ptr);
|
||||
}
|
||||
|
||||
packet->setSubstructArrayDataByName("spells", "spell_id", spell_entry->spell_id, 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "type", spell_entry->type, 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "recast_available", spell_entry->recast_available, 0, ptr);
|
||||
|
@ -2801,9 +2836,8 @@ EQ2Packet* Player::GetSpellBookUpdatePacket(int16 version) {
|
|||
packet->setSubstructArrayDataByName("spells", "icon", (spell->GetSpellIcon() * -1) - 1, 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "icon_type", spell->GetSpellIconBackdrop(), 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "icon2", spell->GetSpellIconHeroicOp(), 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "unique_id", (spell_entry->tier + 1) * -1, 0, ptr);
|
||||
packet->setSubstructArrayDataByName("spells", "unique_id", (spell_entry->tier + 1) * -1, 0, ptr); //this is actually GetSpellNameCrc(spell->GetName()), but hijacking it for spell tier
|
||||
packet->setSubstructArrayDataByName("spells", "charges", 255, 0, ptr);
|
||||
|
||||
// Beastlord and Channeler spell support
|
||||
if (spell->GetSpellData()->savage_bar == 1)
|
||||
packet->setSubstructArrayDataByName("spells", "unknown6", 32, 0, ptr); // advantages
|
||||
|
@ -3746,9 +3780,7 @@ bool Player::AddXP(int32 xp_amount){
|
|||
return false;
|
||||
}
|
||||
xp_amount -= GetNeededXP() - GetXP();
|
||||
SetLevel(GetLevel() + 1);
|
||||
SetXP(0);
|
||||
SetNeededXP();
|
||||
SetLevel(GetLevel() + 1);
|
||||
}
|
||||
SetXP(GetXP() + xp_amount);
|
||||
GetPlayerInfo()->CalculateXPPercentages();
|
||||
|
@ -4039,7 +4071,7 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
|
|||
if(!all_quests && !itr->second->GetUpdateRequired())
|
||||
continue;
|
||||
quest = itr->second;
|
||||
if(!quest->GetDeleted() && !quest->GetCompleted())
|
||||
if(!quest->GetDeleted())
|
||||
packet->setArrayDataByName("active", 1, i);
|
||||
packet->setArrayDataByName("name", quest->GetName(), i);
|
||||
packet->setArrayDataByName("quest_type", quest->GetType(), i);
|
||||
|
@ -4053,8 +4085,10 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
|
|||
packet->setArrayDataByName("visible", 1, i);
|
||||
display_status += QUEST_DISPLAY_STATUS_COMPLETED;
|
||||
}
|
||||
if (updated)
|
||||
if (updated) {
|
||||
packet->setArrayDataByName("quest_updated", 1, i);
|
||||
packet->setArrayDataByName("journal_updated", 1, i);
|
||||
}
|
||||
packet->setArrayDataByName("quest_id", quest->GetQuestID(), i);
|
||||
packet->setArrayDataByName("day", quest->GetDay(), i);
|
||||
packet->setArrayDataByName("month", quest->GetMonth(), i);
|
||||
|
@ -4102,7 +4136,7 @@ PacketStruct* Player::GetQuestJournalPacket(bool all_quests, int16 version, int3
|
|||
//packet->setDataByName("unknown4", 0);
|
||||
packet->setDataByName("visible_quest_id", current_quest_id);
|
||||
}
|
||||
MPlayerQuests.unlock();
|
||||
MPlayerQuests.unlock();
|
||||
packet->setDataByName("player_crc", crc);
|
||||
packet->setDataByName("player_name", GetName());
|
||||
packet->setDataByName("used_quests", total_quests_num - total_completed_quests);
|
||||
|
@ -4144,7 +4178,7 @@ PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 c
|
|||
packet->setArrayDataByName("turned_in", 1);
|
||||
packet->setArrayDataByName("completed", 1);
|
||||
display_status += QUEST_DISPLAY_STATUS_COMPLETED;
|
||||
}
|
||||
}
|
||||
packet->setArrayDataByName("quest_id", quest->GetQuestID());
|
||||
packet->setArrayDataByName("day", quest->GetDay());
|
||||
packet->setArrayDataByName("month", quest->GetMonth());
|
||||
|
@ -4189,8 +4223,10 @@ PacketStruct* Player::GetQuestJournalPacket(Quest* quest, int16 version, int32 c
|
|||
packet->setArrayDataByName("repeatable", 1);
|
||||
|
||||
packet->setArrayDataByName("display_status", display_status);
|
||||
if (updated)
|
||||
packet->setDataByName("quest_updated", 1);
|
||||
if (updated) {
|
||||
packet->setArrayDataByName("quest_updated", 1);
|
||||
packet->setArrayDataByName("journal_updated", 1);
|
||||
}
|
||||
packet->setDataByName("visible_quest_id", quest->GetQuestID());
|
||||
packet->setDataByName("player_crc", crc);
|
||||
packet->setDataByName("player_name", GetName());
|
||||
|
|
|
@ -493,6 +493,7 @@ public:
|
|||
/// <returns>True if the player has enough coins</returns>
|
||||
bool HasCoins(int64 val);
|
||||
void AddSkill(int32 skill_id, int16 current_val, int16 max_val, bool save_needed = false);
|
||||
void RemovePlayerSkill(int32 skill_id, bool save = false);
|
||||
void RemoveSkillFromDB(Skill* skill, bool save = false);
|
||||
void AddSpellBookEntry(int32 spell_id, int8 tier, sint32 slot, int32 type, int32 timer, bool save_needed = false);
|
||||
SpellBookEntry* GetSpellBookSpell(int32 spell_id);
|
||||
|
@ -576,6 +577,11 @@ public:
|
|||
void ClearRemovedSpawn(Spawn* spawn);
|
||||
bool ShouldSendSpawn(Spawn* spawn);
|
||||
Client* client = 0;
|
||||
void SetLevel(int16 level, bool setUpdateFlags = true) {
|
||||
SetInfo(&appearance.level, level, setUpdateFlags);
|
||||
SetXP(0);
|
||||
SetNeededXP();
|
||||
}
|
||||
|
||||
Spawn* GetSpawnWithPlayerID(int32 id){
|
||||
Spawn* spawn = 0;
|
||||
|
@ -890,7 +896,7 @@ public:
|
|||
void LockAllSpells();
|
||||
|
||||
/// <summary>Unlocks all Spells, Combat arts, and Abilities (not trade skill spells)</summary>
|
||||
void UnlockAllSpells(bool modify_recast = false);
|
||||
void UnlockAllSpells(bool modify_recast = false, Spell* exception = 0);
|
||||
|
||||
/// <summary>Locks the given spell as well as all spells with a shared timer</summary>
|
||||
void LockSpell(Spell* spell, int16 recast);
|
||||
|
|
|
@ -302,6 +302,7 @@ Quest::Quest(int32 in_id){
|
|||
reward_coins = 0;
|
||||
reward_coins_max = 0;
|
||||
completed_flag = false;
|
||||
has_sent_last_update = false;
|
||||
enc_level = 0;
|
||||
reward_exp = 0;
|
||||
reward_tsexp = 0;
|
||||
|
@ -345,6 +346,7 @@ Quest::Quest(Quest* old_quest){
|
|||
reward_tsexp = old_quest->reward_tsexp;
|
||||
generated_coin = old_quest->generated_coin;
|
||||
completed_flag = old_quest->completed_flag;
|
||||
has_sent_last_update = old_quest->has_sent_last_update;
|
||||
yellow_name = old_quest->yellow_name;
|
||||
m_questFlags = old_quest->m_questFlags;
|
||||
id = old_quest->id;
|
||||
|
@ -995,7 +997,7 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
|
|||
|
||||
packet->setDataByName("bullets", 1);
|
||||
if (old_completed_quest) {
|
||||
if (version >= 1096) {
|
||||
if (version >= 1096 || version == 546) {
|
||||
packet->setDataByName("complete", 1);
|
||||
packet->setDataByName("complete2", 1);
|
||||
packet->setDataByName("complete3", 1);
|
||||
|
@ -1008,7 +1010,7 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
|
|||
packet->setDataByName("unknown3", 1, 6);
|
||||
}
|
||||
}
|
||||
else if (version >= 1096 && GetCompleted()) {
|
||||
else if ((version >= 1096 || version == 546) && GetCompleted() && HasSentLastUpdate()) { //need to send last quest update before erasing all progress of the quest
|
||||
packet->setDataByName("complete", 1);
|
||||
packet->setDataByName("complete2", 1);
|
||||
packet->setDataByName("complete3", 1);
|
||||
|
@ -1225,12 +1227,15 @@ EQ2Packet* Quest::QuestJournalReply(int16 version, int32 player_crc, Player* pla
|
|||
|
||||
}
|
||||
}
|
||||
if (GetCompleted()) { //mark the last update as being sent, next time we send the quest reply, it will only be a brief portion
|
||||
SetSentLastUpdate(true);
|
||||
}
|
||||
}
|
||||
MQuestSteps.unlock();
|
||||
|
||||
|
||||
string reward_str = "";
|
||||
if (version >= 1096)
|
||||
if (version >= 1096 || version == 546)
|
||||
reward_str = "reward_data_";
|
||||
string tmp = reward_str + "reward";
|
||||
packet->setDataByName(tmp.c_str(), "Quest Reward!");
|
||||
|
|
|
@ -226,6 +226,8 @@ public:
|
|||
Player* GetPlayer();
|
||||
void SetPlayer(Player* in_player);
|
||||
bool GetCompleted();
|
||||
bool HasSentLastUpdate() { return has_sent_last_update; }
|
||||
void SetSentLastUpdate(bool val) { has_sent_last_update = val; }
|
||||
void SetCompletedDescription(string desc);
|
||||
const char* GetCompletedDescription();
|
||||
int32 GetExpReward();
|
||||
|
@ -312,6 +314,7 @@ protected:
|
|||
bool turned_in;
|
||||
bool update_needed;
|
||||
bool deleted;
|
||||
bool has_sent_last_update;
|
||||
|
||||
string completed_description;
|
||||
|
||||
|
|
|
@ -155,6 +155,14 @@ map<int32, Skill*>* PlayerSkillList::GetAllSkills(){
|
|||
return &skills;
|
||||
}
|
||||
|
||||
void PlayerSkillList::SetSkillValuesByType(int8 type, int16 value, bool send_update) {
|
||||
map<int32, Skill*>::iterator itr;
|
||||
for (itr = skills.begin(); itr != skills.end(); itr++) {
|
||||
if (itr->second && itr->second->skill_type == type)
|
||||
SetSkill(itr->second, value, send_update);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSkillList::SetSkillCapsByType(int8 type, int16 value){
|
||||
map<int32, Skill*>::iterator itr;
|
||||
for(itr = skills.begin(); itr != skills.end(); itr++){
|
||||
|
@ -220,19 +228,20 @@ void PlayerSkillList::DecreaseSkill(int32 skill_id, int16 amount){
|
|||
DecreaseSkill(GetSkill(skill_id), amount);
|
||||
}
|
||||
|
||||
void PlayerSkillList::SetSkill(Skill* skill, int16 value){
|
||||
void PlayerSkillList::SetSkill(Skill* skill, int16 value, bool send_update){
|
||||
if(skill){
|
||||
skill->previous_val = skill->current_val;
|
||||
skill->current_val = value;
|
||||
if(skill->current_val > skill->max_val)
|
||||
skill->max_val = skill->current_val;
|
||||
skill->save_needed = true;
|
||||
AddSkillUpdateNeeded(skill);
|
||||
if(send_update)
|
||||
AddSkillUpdateNeeded(skill);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerSkillList::SetSkill(int32 skill_id, int16 value){
|
||||
SetSkill(GetSkill(skill_id), value);
|
||||
void PlayerSkillList::SetSkill(int32 skill_id, int16 value, bool send_update){
|
||||
SetSkill(GetSkill(skill_id), value, send_update);
|
||||
}
|
||||
|
||||
void PlayerSkillList::IncreaseSkillCap(Skill* skill, int16 amount){
|
||||
|
@ -319,9 +328,15 @@ EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
|
|||
PacketStruct* packet = configReader.getStruct("WS_UpdateSkillBook", version);
|
||||
if(packet){
|
||||
if(packet_count < skills.size()){
|
||||
int16 size = 21 * skills.size() + 8;
|
||||
if (version <= 283) {
|
||||
size = 12 * skills.size()+6;
|
||||
int16 size = 0;
|
||||
if (version > 546) {
|
||||
size = 21 * skills.size() + 8;
|
||||
}
|
||||
else if (version <= 283) {
|
||||
size = 12 * skills.size() + 6;
|
||||
}
|
||||
else if (version <= 546) {
|
||||
size = 21 * skills.size() + 7;
|
||||
}
|
||||
if(!orig_packet){
|
||||
xor_packet = new uchar[size];
|
||||
|
@ -360,7 +375,11 @@ EQ2Packet* PlayerSkillList::GetSkillPacket(int16 version){
|
|||
}
|
||||
|
||||
packet->setArrayDataByName("skill_id", skill->skill_id, i);
|
||||
packet->setArrayDataByName("type", skill->skill_type, i);
|
||||
if (version <= 546 && skill->skill_type >= SKILL_TYPE_GENERAL) { //covert it to DOF types
|
||||
packet->setArrayDataByName("type", skill->skill_type-2, i);
|
||||
}
|
||||
else
|
||||
packet->setArrayDataByName("type", skill->skill_type, i);
|
||||
packet->setArrayDataByName("current_val", skill->current_val, i);
|
||||
packet->setArrayDataByName("base_val", skill->current_val, i);// skill->
|
||||
packet->setArrayDataByName("skill_delta", 0, i);// skill_with_bonuses- skill->current_val
|
||||
|
|
|
@ -25,15 +25,29 @@
|
|||
#include "../common/types.h"
|
||||
#include "MutexMap.h"
|
||||
|
||||
#define SKILL_TYPE_COMBAT 1
|
||||
#define SKILL_TYPE_WEAPONRY 1
|
||||
#define SKILL_TYPE_SPELLCASTING 2
|
||||
#define SKILL_TYPE_AVOIDANCE 3
|
||||
#define SKILL_TYPE_ARMOR 4
|
||||
#define SKILL_TYPE_SHIELD 5
|
||||
#define SKILL_TYPE_HARVESTING 6
|
||||
#define SKILL_TYPE_ARTISAN 7
|
||||
#define SKILL_TYPE_CRAFTSMAN 8
|
||||
#define SKILL_TYPE_OUTFITTER 9
|
||||
#define SKILL_TYPE_SCHOLAR 10
|
||||
#define SKILL_TYPE_GENERAL 12
|
||||
#define SKILL_TYPE_GENERAL 13
|
||||
#define SKILL_TYPE_LANGUAGE 14
|
||||
#define SKILL_TYPE_CLASS 15
|
||||
#define SKILL_TYPE_COMBAT 16
|
||||
#define SKILL_TYPE_WEAPON 17
|
||||
#define SKILL_TYPE_TSKNOWLEDGE 18
|
||||
|
||||
#define SKILL_TYPE_GENERAL_DOF 11
|
||||
#define SKILL_TYPE_LANGUAGE_DOF 12
|
||||
#define SKILL_TYPE_CLASS_DOF 13
|
||||
#define SKILL_TYPE_COMBAT_DOF 14
|
||||
#define SKILL_TYPE_WEAPON_DOF 15
|
||||
#define SKILL_TYPE_TSKNOWLEDGE_DOF 16
|
||||
|
||||
#define SKILL_ID_SCULPTING 1039865549
|
||||
#define SKILL_ID_FLETCHING 3076004370
|
||||
|
@ -44,6 +58,13 @@
|
|||
#define SKILL_ID_SCRIBING 773137566
|
||||
#define SKILL_ID_CHEMISTRY 2557647574
|
||||
#define SKILL_ID_ARTIFICING 3330500131
|
||||
#define SKILL_ID_ARTIFICING 3330500131
|
||||
|
||||
//the following update the current_value to the max_value as soon as the max_value is updated
|
||||
#define SKILL_ID_DUALWIELD 1852383242
|
||||
#define SKILL_ID_FISTS 3177806075
|
||||
#define SKILL_ID_DESTROYING 3429135390
|
||||
#define SKILL_ID_MAGIC_AFFINITY 2072844078
|
||||
|
||||
/* Each SkillBonus is comprised of multiple possible skill bonus values. This is so one spell can modify
|
||||
more than one skill */
|
||||
|
@ -107,8 +128,8 @@ public:
|
|||
void IncreaseSkill(int32 skill_id, int16 amount);
|
||||
void DecreaseSkill(Skill* skill, int16 amount);
|
||||
void DecreaseSkill(int32 skill_id, int16 amount);
|
||||
void SetSkill(Skill* skill, int16 value);
|
||||
void SetSkill(int32 skill_id, int16 value);
|
||||
void SetSkill(Skill* skill, int16 value, bool send_update = true);
|
||||
void SetSkill(int32 skill_id, int16 value, bool send_update = true);
|
||||
|
||||
void IncreaseSkillCap(Skill* skill, int16 amount);
|
||||
void IncreaseSkillCap(int32 skill_id, int16 amount);
|
||||
|
@ -119,6 +140,7 @@ public:
|
|||
void IncreaseAllSkillCaps(int16 value);
|
||||
void IncreaseSkillCapsByType(int8 type, int16 value);
|
||||
void SetSkillCapsByType(int8 type, int16 value);
|
||||
void SetSkillValuesByType(int8 type, int16 value, bool send_update = true);
|
||||
void AddSkillUpdateNeeded(Skill* skill);
|
||||
|
||||
void AddSkillBonus(int32 spell_id, int32 skill_id, float value);
|
||||
|
|
|
@ -337,14 +337,14 @@ void Spawn::InitializeVisPacketData(Player* player, PacketStruct* vis_packet) {
|
|||
vis_flags += 4;
|
||||
}
|
||||
|
||||
if (version <= 546 && vis_flags > 0)
|
||||
if (version <= 546 && (vis_flags > 1 || appearance.display_hand_icon > 0)) //interactable
|
||||
vis_flags = 1;
|
||||
|
||||
vis_packet->setDataByName("vis_flags", vis_flags);
|
||||
|
||||
|
||||
if (MeetsSpawnAccessRequirements(player))
|
||||
if (MeetsSpawnAccessRequirements(player)) {
|
||||
vis_packet->setDataByName("hand_flag", appearance.display_hand_icon);
|
||||
}
|
||||
else {
|
||||
if ((req_quests_override & 256) > 0)
|
||||
vis_packet->setDataByName("hand_flag", 1);
|
||||
|
@ -1006,7 +1006,9 @@ EQ2Packet* Spawn::spawn_update_packet(Player* player, int16 version, bool overri
|
|||
ptr += pos_packet_size;
|
||||
memcpy(ptr, vis_changes ? vis_changes : &null_byte, tmp_vis_packet_size);
|
||||
|
||||
EQ2Packet* ret_packet = new EQ2Packet(OP_ClientCmdMsg, tmp, size);
|
||||
EQ2Packet* ret_packet = 0;
|
||||
if(info_packet_size + pos_packet_size + vis_packet_size > 0)
|
||||
ret_packet = new EQ2Packet(OP_ClientCmdMsg, tmp, size);
|
||||
delete[] tmp;
|
||||
safe_delete_array(info_changes);
|
||||
safe_delete_array(vis_changes);
|
||||
|
@ -2224,7 +2226,8 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
|
|||
}
|
||||
if (GetHP() <= 0 && IsEntity()) {
|
||||
packet->setDataByName("corpse", 1);
|
||||
packet->setDataByName("loot_icon", 1);
|
||||
if(HasLoot())
|
||||
packet->setDataByName("loot_icon", 1);
|
||||
}
|
||||
if (!IsPlayer())
|
||||
packet->setDataByName("npc", 1);
|
||||
|
|
|
@ -152,6 +152,13 @@
|
|||
#define INFO_VIS_FLAG_MOUNTED 4
|
||||
#define INFO_VIS_FLAG_CROUCH 8
|
||||
|
||||
#define ENCOUNTER_STATE_NONE 0
|
||||
#define ENCOUNTER_STATE_AVAILABLE 1
|
||||
#define ENCOUNTER_STATE_BROKEN 2
|
||||
#define ENCOUNTER_STATE_LOCKED 3
|
||||
#define ENCOUNTER_STATE_OVERMATCHED 4
|
||||
#define ENCOUNTER_STATE_NO_REWARD 5
|
||||
|
||||
using namespace std;
|
||||
class Spell;
|
||||
class ZoneServer;
|
||||
|
@ -293,6 +300,7 @@ public:
|
|||
entity_command->default_allow_list = default_allow_list;
|
||||
return entity_command;
|
||||
}
|
||||
virtual Client* GetClient() { return 0; }
|
||||
void AddChangedZoneSpawn();
|
||||
void AddPrimaryEntityCommand(const char* name, float distance, const char* command, const char* error_text, int16 cast_time, int32 spell_visual, bool defaultDenyList = false, Player* player = NULL);
|
||||
void RemovePrimaryEntityCommand(const char* command);
|
||||
|
@ -446,7 +454,7 @@ public:
|
|||
void SetEncounterLevel(int8 enc_level, bool setUpdateFlags = true){
|
||||
SetInfo(&appearance.encounter_level, enc_level, setUpdateFlags);
|
||||
}
|
||||
void SetLevel(int16 level, bool setUpdateFlags = true){
|
||||
virtual void SetLevel(int16 level, bool setUpdateFlags = true){
|
||||
SetInfo(&appearance.level, level, setUpdateFlags);
|
||||
}
|
||||
void SetTSLevel(int16 tradeskill_level, bool setUpdateFlags = true){
|
||||
|
|
|
@ -392,12 +392,33 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason){
|
|||
if(target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0){
|
||||
Client* client = target->GetZone()->GetClientBySpawn(target);
|
||||
if(client){
|
||||
bool send_to_sender = true;
|
||||
string fade_message = spell->spell->GetSpellData()->fade_message;
|
||||
if(fade_message.find("%t") != string::npos)
|
||||
fade_message.replace(fade_message.find("%t"), 2, target->GetName());
|
||||
fade_message.replace(fade_message.find("%t"), 2, target->GetName());
|
||||
client->Message(CHANNEL_SPELLS_OTHER, fade_message.c_str());
|
||||
}
|
||||
}
|
||||
if (target && target->IsPlayer() && spell->spell->GetSpellData()->fade_message.length() > 0) {
|
||||
Client* client = target->GetZone()->GetClientBySpawn(target);
|
||||
if (client) {
|
||||
bool send_to_sender = true;
|
||||
string fade_message_others = spell->spell->GetSpellData()->fade_message_others;
|
||||
if (fade_message_others.find("%t") != string::npos)
|
||||
fade_message_others.replace(fade_message_others.find("%t"), 2, target->GetName());
|
||||
if (fade_message_others.find("%c") != string::npos)
|
||||
fade_message_others.replace(fade_message_others.find("%c"), 2, spell->caster->GetName());
|
||||
if (fade_message_others.find("%T") != string::npos) {
|
||||
fade_message_others.replace(fade_message_others.find("%T"), 2, target->GetName());
|
||||
send_to_sender = false;
|
||||
}
|
||||
if (fade_message_others.find("%C") != string::npos) {
|
||||
fade_message_others.replace(fade_message_others.find("%C"), 2, spell->caster->GetName());
|
||||
send_to_sender = false;
|
||||
}
|
||||
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, fade_message_others.c_str(), target, 50, send_to_sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
|
||||
ret = true;
|
||||
|
@ -522,7 +543,10 @@ void SpellProcess::SendStartCast(LuaSpell* spell, Client* client){
|
|||
|
||||
void SpellProcess::SendFinishedCast(LuaSpell* spell, Client* client){
|
||||
if(client && spell && spell->spell){
|
||||
UnlockAllSpells(client);
|
||||
if (spell->spell->GetSpellData()->cast_type == SPELL_CAST_TYPE_TOGGLE)
|
||||
UnlockAllSpells(client, spell->spell);
|
||||
else
|
||||
UnlockAllSpells(client);
|
||||
if(spell->resisted && spell->spell->GetSpellData()->recast > 0)
|
||||
CheckRecast(spell->spell, client->GetPlayer(), 0.5); // half sec recast on resisted spells
|
||||
else if (!spell->interrupted && spell->spell->GetSpellData()->cast_type != SPELL_CAST_TYPE_TOGGLE)
|
||||
|
@ -557,9 +581,9 @@ void SpellProcess::LockAllSpells(Client* client){
|
|||
}
|
||||
}
|
||||
|
||||
void SpellProcess::UnlockAllSpells(Client* client){
|
||||
void SpellProcess::UnlockAllSpells(Client* client, Spell* exception){
|
||||
if(client)
|
||||
client->GetPlayer()->UnlockAllSpells();
|
||||
client->GetPlayer()->UnlockAllSpells(false, exception);
|
||||
}
|
||||
|
||||
void SpellProcess::UnlockSpell(Client* client, Spell* spell){
|
||||
|
@ -1447,11 +1471,20 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive){
|
|||
}
|
||||
if(spell->spell->GetSpellData()->effect_message.length() > 0){
|
||||
string effect_message = spell->spell->GetSpellData()->effect_message;
|
||||
if(effect_message.find("%t") < 0xFFFFFFFF)
|
||||
bool send_to_sender = true;
|
||||
if(effect_message.find("%t") != string::npos)
|
||||
effect_message.replace(effect_message.find("%t"), 2, target->GetName());
|
||||
if (effect_message.find("%c") != string::npos)
|
||||
effect_message.replace(effect_message.find("%c"), 2, spell->caster->GetName());
|
||||
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, effect_message.c_str(), target, 50);
|
||||
if (effect_message.find("%T") != string::npos) {
|
||||
effect_message.replace(effect_message.find("%T"), 2, target->GetName());
|
||||
send_to_sender = false;
|
||||
}
|
||||
if (effect_message.find("%C") != string::npos) {
|
||||
effect_message.replace(effect_message.find("%C"), 2, spell->caster->GetName());
|
||||
send_to_sender = false;
|
||||
}
|
||||
spell->caster->GetZone()->SimpleMessage(CHANNEL_SPELLS_OTHER, effect_message.c_str(), target, 50, send_to_sender);
|
||||
}
|
||||
target->GetZone()->CallSpawnScript(target, SPAWN_SCRIPT_CASTED_ON, spell->caster, spell->spell->GetName());
|
||||
}
|
||||
|
@ -1466,7 +1499,13 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive){
|
|||
|
||||
//LogWrite(SPELL__ERROR, 0, "Spell", "No precast function found for %s", ((Entity*)target)->GetName());
|
||||
target = zone->GetSpawnByID(spell->targets.at(i));
|
||||
|
||||
if (!target && spell->targets.at(i) == spell->caster->GetID()) {
|
||||
target = spell->caster;
|
||||
}
|
||||
if (!target) {
|
||||
client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Zone has not finished loading process yet. Try again later.");
|
||||
continue;
|
||||
}
|
||||
if (i == 0 && !spell->spell->GetSpellData()->not_maintained) {
|
||||
spell->caster->AddMaintainedSpell(spell);
|
||||
//((Entity*)target)->AddMaintainedSpell(spell);
|
||||
|
|
|
@ -244,7 +244,7 @@ public:
|
|||
|
||||
/// <summary>Unlock all the spells for the given client</summary>
|
||||
/// <param name='client'>Client to unlock the spells for</param>
|
||||
void UnlockAllSpells(Client* client);
|
||||
void UnlockAllSpells(Client* client, Spell* exception = 0);
|
||||
|
||||
/// <summary>Unlock a single spell for the given client</summary>
|
||||
/// <param name='client'>The client to unlock the spell for</param>
|
||||
|
|
|
@ -82,6 +82,7 @@ Spell::Spell(Spell* host_spell)
|
|||
spell->duration_until_cancel = host_spell->GetSpellData()->duration_until_cancel;
|
||||
spell->effect_message = string(host_spell->GetSpellData()->effect_message);
|
||||
spell->fade_message = string(host_spell->GetSpellData()->fade_message);
|
||||
spell->fade_message_others = string(host_spell->GetSpellData()->fade_message_others);
|
||||
|
||||
spell->friendly_spell = host_spell->GetSpellData()->friendly_spell;
|
||||
spell->group_spell = host_spell->GetSpellData()->group_spell;
|
||||
|
@ -774,8 +775,12 @@ void Spell::SetPacketInformation(PacketStruct* packet, Client* client, bool disp
|
|||
packet->setSubstructDataByName("spell_info", "tier", spell->tier);
|
||||
packet->setSubstructDataByName("spell_info", "power_req", power_req);
|
||||
packet->setSubstructDataByName("spell_info", "power_upkeep", spell->power_upkeep);
|
||||
|
||||
packet->setSubstructDataByName("spell_info", "cast_time", spell->cast_time);
|
||||
if (packet->GetVersion() <= 546) {//cast times are displayed differently on new clients
|
||||
packet->setSubstructDataByName("spell_info", "cast_time", spell->cast_time/10);
|
||||
}
|
||||
else {
|
||||
packet->setSubstructDataByName("spell_info", "cast_time", spell->cast_time);
|
||||
}
|
||||
packet->setSubstructDataByName("spell_info", "recast", spell->recast);
|
||||
packet->setSubstructDataByName("spell_info", "radius", spell->radius);
|
||||
packet->setSubstructDataByName("spell_info", "req_concentration", spell->req_concentration);
|
||||
|
@ -1095,10 +1100,10 @@ EQ2Packet* Spell::SerializeSpell(Client* client, bool display, bool trait_displa
|
|||
version = client->GetVersion();
|
||||
if (!struct_name)
|
||||
struct_name = "WS_ExamineSpellInfo";
|
||||
if (version <= 283) {
|
||||
if (version <= 546) {
|
||||
if (packet_type == 1)
|
||||
struct_name = "WS_ExamineEffectInfo";
|
||||
else if (!display)
|
||||
else if (!display && version<=283)
|
||||
struct_name = "WS_ExaminePartialSpellInfo";
|
||||
else
|
||||
struct_name = "WS_ExamineSpellInfo";
|
||||
|
@ -1501,6 +1506,11 @@ bool Spell::GetSpellData(lua_State* state, std::string field)
|
|||
lua_interface->SetStringValue(state, GetSpellData()->fade_message.c_str());
|
||||
valSet = true;
|
||||
}
|
||||
else if (field == "fade_message_others")
|
||||
{
|
||||
lua_interface->SetStringValue(state, GetSpellData()->fade_message_others.c_str());
|
||||
valSet = true;
|
||||
}
|
||||
else if (field == "cast_type")
|
||||
{
|
||||
lua_interface->SetSInt32Value(state, GetSpellData()->cast_type);
|
||||
|
@ -1883,6 +1893,12 @@ bool Spell::SetSpellData(lua_State* state, std::string field, int8 fieldArg)
|
|||
GetSpellData()->fade_message = fade_message;
|
||||
valSet = true;
|
||||
}
|
||||
else if (field == "fade_message_others")
|
||||
{
|
||||
string fade_message_others = lua_interface->GetStringValue(state, fieldArg);
|
||||
GetSpellData()->fade_message_others = fade_message_others;
|
||||
valSet = true;
|
||||
}
|
||||
else if (field == "cast_type")
|
||||
{
|
||||
int8 cast_type = lua_interface->GetInt8Value(state, fieldArg);
|
||||
|
|
|
@ -259,6 +259,7 @@ struct SpellData{
|
|||
EQ2_16BitString description;
|
||||
string success_message;
|
||||
string fade_message;
|
||||
string fade_message_others;
|
||||
int8 cast_type;
|
||||
string lua_script;
|
||||
int32 call_frequency;
|
||||
|
@ -335,7 +336,8 @@ public:
|
|||
bool CastWhileMezzed();
|
||||
bool CastWhileStifled();
|
||||
bool CastWhileFeared();
|
||||
|
||||
bool GetStayLocked() { return stay_locked; }
|
||||
void StayLocked(bool val) { stay_locked = val; }
|
||||
|
||||
vector<SpellDisplayEffect*> effects;
|
||||
vector<LUAData*> lua_data;
|
||||
|
@ -343,6 +345,7 @@ public:
|
|||
void LockSpellInfo() { MSpellInfo.lock(); }
|
||||
void UnlockSpellInfo() { MSpellInfo.unlock(); }
|
||||
private:
|
||||
bool stay_locked = false;
|
||||
bool heal_spell;
|
||||
bool buff_spell;
|
||||
bool damage_spell;
|
||||
|
|
|
@ -2276,6 +2276,43 @@ void World::PurgeStartingLists()
|
|||
MStartingLists.releasewritelock();
|
||||
}
|
||||
|
||||
void World::SetReloadingSubsystem(string subsystem) {
|
||||
MReloadingSubsystems.lock();
|
||||
reloading_subsystems[subsystem] = Timer::GetCurrentTime2();
|
||||
MReloadingSubsystems.unlock();
|
||||
}
|
||||
|
||||
void World::RemoveReloadingSubSystem(string subsystem) {
|
||||
MReloadingSubsystems.lock();
|
||||
if (reloading_subsystems.count(subsystem) > 0)
|
||||
reloading_subsystems.erase(subsystem);
|
||||
MReloadingSubsystems.unlock();
|
||||
}
|
||||
|
||||
bool World::IsReloadingSubsystems() {
|
||||
bool result = false;
|
||||
MReloadingSubsystems.lock();
|
||||
result = reloading_subsystems.size() > 0;
|
||||
MReloadingSubsystems.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
map<string, int32> World::GetOldestReloadingSubsystem() {
|
||||
map<string, int32> result;
|
||||
MReloadingSubsystems.lock();
|
||||
int32 current_time = Timer::GetCurrentTime2();
|
||||
map<string, int32>::iterator itr;
|
||||
int32 oldest = current_time;
|
||||
string oldestname = "";
|
||||
for (itr = reloading_subsystems.begin(); itr != reloading_subsystems.end(); itr++) {
|
||||
if (itr->second < oldest)
|
||||
oldestname = itr->first;
|
||||
}
|
||||
result[oldestname] = oldest;
|
||||
MReloadingSubsystems.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
void ZoneList::WatchdogHeartbeat()
|
||||
{
|
||||
list<ZoneServer*>::iterator zone_iter;
|
||||
|
@ -2290,9 +2327,8 @@ void ZoneList::WatchdogHeartbeat()
|
|||
{
|
||||
int32 curTime = Timer::GetCurrentTime2();
|
||||
sint64 diff = (sint64)curTime - (sint64)tmp->GetWatchdogTime();
|
||||
if (diff > 60000)
|
||||
{
|
||||
tmp->SetWatchdogTime(Timer::GetCurrentTime2()); // reset so we don't continuously flood this heartbeat
|
||||
if (diff > 120000)
|
||||
{
|
||||
LogWrite(WORLD__ERROR, 1, "World", "Zone %s is hung for %i milliseconds.. attempting to cancel threads...", tmp->GetZoneName(), diff);
|
||||
#ifndef WIN32
|
||||
tmp->CancelThreads();
|
||||
|
@ -2301,10 +2337,38 @@ void ZoneList::WatchdogHeartbeat()
|
|||
#endif
|
||||
MZoneList.releasewritelock(__FUNCTION__, __LINE__);
|
||||
match = true;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
else if (diff > 90000 && !tmp->isZoneShuttingDown())
|
||||
{
|
||||
tmp->SetWatchdogTime(Timer::GetCurrentTime2()); // reset so we don't continuously flood this heartbeat
|
||||
map<string, int32> oldest_process = world.GetOldestReloadingSubsystem();
|
||||
if (oldest_process.size() > 0) {
|
||||
map<string, int32>::iterator itr = oldest_process.begin();
|
||||
LogWrite(WORLD__ERROR, 1, "World", "Zone %s is hung for %i milliseconds.. while waiting for %s to reload...attempting shutdown", tmp->GetZoneName(), diff, itr->first);
|
||||
}
|
||||
else
|
||||
LogWrite(WORLD__ERROR, 1, "World", "Zone %s is hung for %i milliseconds.. attempting shutdown", tmp->GetZoneName(), diff);
|
||||
tmp->Shutdown();
|
||||
}
|
||||
else if (diff > 60000)
|
||||
{
|
||||
if (world.IsReloadingSubsystems()) {
|
||||
if (world.GetSuppressedWarningTime() == 0) {
|
||||
world.SetSuppressedWarning();
|
||||
map<string, int32> oldest_process = world.GetOldestReloadingSubsystem();
|
||||
if (oldest_process.size() > 0) {
|
||||
map<string, int32>::iterator itr = oldest_process.begin();
|
||||
LogWrite(WORLD__ERROR, 1, "World", "Zone %s is hung for %i milliseconds.. while waiting for %s to reload...", tmp->GetZoneName(), diff, itr->first);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (diff > 30000 && !tmp->isZoneShuttingDown())
|
||||
{
|
||||
if (world.IsReloadingSubsystems())
|
||||
continue;
|
||||
LogWrite(WORLD__ERROR, 1, "World", "Zone %s is hung for %i milliseconds.. attempting shutdown", tmp->GetZoneName(), diff);
|
||||
tmp->Shutdown();
|
||||
}
|
||||
|
|
|
@ -474,7 +474,7 @@ class ZoneList {
|
|||
void ReloadClientQuests();
|
||||
bool DepopFinished();
|
||||
void Depop();
|
||||
void Repop();
|
||||
void Repop();
|
||||
void DeleteSpellProcess();
|
||||
void LoadSpellProcess();
|
||||
void ProcessWhoQuery(const char* query, Client* client);
|
||||
|
@ -613,10 +613,22 @@ public:
|
|||
multimap<int8, multimap<int8, StartingSkill>*> starting_skills;
|
||||
multimap<int8, multimap<int8, StartingSpell>*> starting_spells;
|
||||
Mutex MStartingLists;
|
||||
void SetReloadingSubsystem(string subsystem);
|
||||
void RemoveReloadingSubSystem(string subsystem);
|
||||
|
||||
bool IsReloadingSubsystems();
|
||||
int32 GetSuppressedWarningTime() {
|
||||
return suppressed_warning;
|
||||
}
|
||||
void SetSuppressedWarning() { suppressed_warning = Timer::GetCurrentTime2(); }
|
||||
map<string, int32> GetOldestReloadingSubsystem();
|
||||
|
||||
private:
|
||||
int32 suppressed_warning = 0;
|
||||
map<string, int32> reloading_subsystems;
|
||||
//void RemovePlayerFromGroup(PlayerGroup* group, GroupMemberInfo* info, bool erase = true);
|
||||
//void DeleteGroupMember(GroupMemberInfo* info);
|
||||
|
||||
Mutex MReloadingSubsystems;
|
||||
Mutex MMerchantList;
|
||||
Mutex MSpawnScripts;
|
||||
Mutex MZoneScripts;
|
||||
|
|
|
@ -287,6 +287,12 @@ int32 WorldDatabase::LoadSkills()
|
|||
skill->description.data = string(row[3]);
|
||||
skill->description.size = skill->description.data.length();
|
||||
skill->skill_type = strtoul(row[4], NULL, 0);
|
||||
//these two need to be converted to the correct numbers
|
||||
if(skill->skill_type == 13)
|
||||
skill->skill_type = SKILL_TYPE_LANGUAGE;
|
||||
else if(skill->skill_type == 12)
|
||||
skill->skill_type = SKILL_TYPE_GENERAL;
|
||||
|
||||
skill->display = atoi(row[5]);
|
||||
master_skill_list.AddSkill(skill);
|
||||
total++;
|
||||
|
@ -3284,6 +3290,7 @@ bool WorldDatabase::SaveSpawnEntry(Spawn* spawn, const char* spawn_location_name
|
|||
LogWrite(SPAWN__ERROR, 0, "Spawn", "Error in SaveSpawnEntry query '%s': %s", query2.GetQuery(), query2.GetError());
|
||||
return false;
|
||||
}
|
||||
spawn->SetSpawnLocationPlacementID(query2.GetLastInsertedID());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3343,6 +3350,8 @@ int32 WorldDatabase::GetSpawnLocationCount(int32 location, Spawn* spawn){
|
|||
MYSQL_RES* result = 0;
|
||||
if(spawn)
|
||||
result = query.RunQuery2(Q_SELECT, "SELECT count(id) FROM spawn_location_entry where spawn_location_id=%u and spawn_id=%u", location, spawn->GetDatabaseID());
|
||||
else
|
||||
result = query.RunQuery2(Q_SELECT, "SELECT count(id) FROM spawn_location_entry where spawn_location_id=%u", location);
|
||||
if(result && mysql_num_rows(result) > 0){
|
||||
MYSQL_ROW row;
|
||||
while(result && (row = mysql_fetch_row(result)) && row[0]){
|
||||
|
@ -4310,7 +4319,7 @@ void WorldDatabase::LoadSpells()
|
|||
int32 total = 0;
|
||||
map<int32, vector<LevelArray*> >* level_data = LoadSpellClasses();
|
||||
|
||||
if( !database_new.Select(&result, "SELECT s.`id`, ts.spell_id, ts.index, `name`, `description`, `type`, `class_skill`, `mastery_skill`, `tier`, `is_aa`,`hp_req`, `power_req`,`power_by_level`, `cast_time`, `recast`, `radius`, `max_aoe_targets`, `req_concentration`, `range`, `duration1`, `duration2`, `resistibility`, `hp_upkeep`, `power_upkeep`, `duration_until_cancel`, `target_type`, `recovery`, `power_req_percent`, `hp_req_percent`, `icon`, `icon_heroic_op`, `icon_backdrop`, `success_message`, `fade_message`, `cast_type`, `lua_script`, `call_frequency`, `interruptable`, `spell_visual`, `effect_message`, `min_range`, `can_effect_raid`, `affect_only_group_members`, `hit_bonus`, `display_spell_tier`, `friendly_spell`, `group_spell`, `spell_book_type`, spell_type+0, s.is_active, savagery_req, savagery_req_percent, savagery_upkeep, dissonance_req, dissonance_req_percent, dissonance_upkeep, linked_timer_id, det_type, incurable, control_effect_type, cast_while_moving, casting_flags, persist_through_death, not_maintained, savage_bar, savage_bar_slot, soe_spell_crc, 0xffffffff-CRC32(s.`name`) as 'spell_name_crc' "
|
||||
if( !database_new.Select(&result, "SELECT s.`id`, ts.spell_id, ts.index, `name`, `description`, `type`, `class_skill`, `mastery_skill`, `tier`, `is_aa`,`hp_req`, `power_req`,`power_by_level`, `cast_time`, `recast`, `radius`, `max_aoe_targets`, `req_concentration`, `range`, `duration1`, `duration2`, `resistibility`, `hp_upkeep`, `power_upkeep`, `duration_until_cancel`, `target_type`, `recovery`, `power_req_percent`, `hp_req_percent`, `icon`, `icon_heroic_op`, `icon_backdrop`, `success_message`, `fade_message`, `fade_message_others`, `cast_type`, `lua_script`, `call_frequency`, `interruptable`, `spell_visual`, `effect_message`, `min_range`, `can_effect_raid`, `affect_only_group_members`, `hit_bonus`, `display_spell_tier`, `friendly_spell`, `group_spell`, `spell_book_type`, spell_type+0, s.is_active, savagery_req, savagery_req_percent, savagery_upkeep, dissonance_req, dissonance_req_percent, dissonance_upkeep, linked_timer_id, det_type, incurable, control_effect_type, cast_while_moving, casting_flags, persist_through_death, not_maintained, savage_bar, savage_bar_slot, soe_spell_crc, 0xffffffff-CRC32(s.`name`) as 'spell_name_crc' "
|
||||
"FROM (spells s, spell_tiers st) "
|
||||
"LEFT JOIN spell_ts_ability_index ts "
|
||||
"ON s.`id` = ts.spell_id "
|
||||
|
@ -4418,6 +4427,10 @@ void WorldDatabase::LoadSpells()
|
|||
if( message.length() > 0 )
|
||||
data->fade_message = string(message);
|
||||
|
||||
message = result.GetStringStr("fade_message_others");
|
||||
if (message.length() > 0)
|
||||
data->fade_message_others = string(message);
|
||||
|
||||
message = result.GetStringStr("effect_message");
|
||||
if( message.length() > 0 )
|
||||
data->effect_message = string(message);
|
||||
|
|
|
@ -1348,6 +1348,18 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
HandleLoot(app);
|
||||
break;
|
||||
}
|
||||
case OP_WaypointSelectMsg: {
|
||||
PacketStruct* packet = configReader.getStruct("WS_WaypointSelect", GetVersion());
|
||||
if (packet) {
|
||||
if (packet->LoadPacketData(app->pBuffer, app->size)) {
|
||||
int32 selection = packet->getType_int32_ByName("selection");
|
||||
if (selection > 0) {
|
||||
SelectWaypoint(selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_KnowledgeWindowSlotMappingMsg: {
|
||||
LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_KnowledgeWindowSlotMappingMsg", opcode, opcode);
|
||||
PacketStruct* packet = configReader.getStruct("WS_SpellSlotMapping", GetVersion());
|
||||
|
@ -1572,9 +1584,18 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
else {
|
||||
EQ2_16BitString command = packet->getType_EQ2_16BitString_ByName("command");
|
||||
if (command.size > 0) {
|
||||
string command_name = command.data;
|
||||
if (command_name.find(" ") < 0xFFFFFFFF)
|
||||
command_name = command_name.substr(0, command_name.find(" "));
|
||||
string command_name = command.data;
|
||||
if (command_name.find(" ") < 0xFFFFFFFF) {
|
||||
if (GetVersion() <= 546) { //this version uses commands in the form "Buy From Merchant" instead of buy_from_merchant
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while(pos != string::npos){
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
}
|
||||
else
|
||||
command_name = command_name.substr(0, command_name.find(" "));
|
||||
}
|
||||
int32 handler = commands.GetCommandHandler(command_name.c_str());
|
||||
if (handler != 0xFFFFFFFF) {
|
||||
if (command.data == command_name) {
|
||||
|
@ -1591,7 +1612,15 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
if (spawn && spawn->IsNPC()) {
|
||||
if (EntityCommandPrecheck(spawn, command.data.c_str())) {
|
||||
if (!((NPC*)spawn)->HandleUse(this, command.data)) {
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unhandled command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
command_name = command.data;
|
||||
string::size_type pos = command_name.find(" ");
|
||||
while (pos != string::npos) {
|
||||
command_name.replace(pos, 1, "_");
|
||||
pos = command_name.find(" ");
|
||||
}
|
||||
if (!((NPC*)spawn)->HandleUse(this, command_name)) { //convert the spaces to underscores and see if that makes a difference
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Unhandled command in OP_EntityVerbsVerbMsg: %s", command.data.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2458,7 +2487,8 @@ void Client::HandleSkillInfoRequest(EQApplicationPacket* app) {
|
|||
|
||||
void Client::HandleExamineInfoRequest(EQApplicationPacket* app) {
|
||||
PacketStruct* request = 0;
|
||||
|
||||
if (!app || app->size == 0)
|
||||
return;
|
||||
//LogWrite(CCLIENT__DEBUG, 0, "Client", "Request2:");
|
||||
//DumpPacket(app);
|
||||
|
||||
|
@ -3341,7 +3371,7 @@ void Client::SimpleMessage(int8 color, const char* message) {
|
|||
}
|
||||
}
|
||||
|
||||
void Client::SendSpellUpdate(Spell* spell) {
|
||||
void Client::SendSpellUpdate(Spell* spell, bool add_silently, bool add_to_hotbar) {
|
||||
PacketStruct* packet = configReader.getStruct("WS_SpellGainedMsg", GetVersion());
|
||||
if (packet) {
|
||||
int8 xxx = spell->GetSpellData()->is_aa;
|
||||
|
@ -3349,6 +3379,10 @@ void Client::SendSpellUpdate(Spell* spell) {
|
|||
packet->setDataByName("spell_id", spell->GetSpellID());
|
||||
packet->setDataByName("unique_id", spell->GetSpellData()->spell_name_crc);
|
||||
packet->setDataByName("spell_name", spell->GetName());
|
||||
if(add_silently)
|
||||
packet->setDataByName("add_silently", 1);
|
||||
if(add_to_hotbar)
|
||||
packet->setDataByName("add_to_hotbar", 1);
|
||||
packet->setDataByName("unknown", xxx);
|
||||
packet->setDataByName("display_spell_tier", 1);
|
||||
packet->setDataByName("unknown3", 1);
|
||||
|
@ -4085,8 +4119,9 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
}
|
||||
}
|
||||
|
||||
if (new_level > old_level)
|
||||
if (new_level > old_level) {
|
||||
player->UpdatePlayerHistory(HISTORY_TYPE_XP, HISTORY_SUBTYPE_ADVENTURE, new_level, player->GetAdventureClass());
|
||||
}
|
||||
|
||||
if (player->GetPet()) {
|
||||
NPC* pet = (NPC*)player->GetPet();
|
||||
|
@ -4165,13 +4200,37 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
LogWrite(WORLD__DEBUG, 0, "World", "Player: %s leveled from %u to %u", GetPlayer()->GetName(), old_level, new_level);
|
||||
int16 new_skill_cap = 5 * new_level;
|
||||
PlayerSkillList* player_skills = player->GetSkills();
|
||||
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_ARMOR, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_SHIELD, new_skill_cap);
|
||||
//SKILL_TYPE_ARMOR/SKILL_TYPE_SHIELD always has the same current / max values
|
||||
player_skills->SetSkillValuesByType(SKILL_TYPE_ARMOR, new_skill_cap, false);
|
||||
player_skills->SetSkillValuesByType(SKILL_TYPE_SHIELD, new_skill_cap, false);
|
||||
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_CLASS, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_WEAPON, new_skill_cap);
|
||||
//SKILL_TYPE_CLASS/SKILL_TYPE_WEAPON always has the same current/max values
|
||||
player_skills->SetSkillValuesByType(SKILL_TYPE_CLASS, new_skill_cap, false);
|
||||
player_skills->SetSkillValuesByType(SKILL_TYPE_WEAPON, new_skill_cap, false);
|
||||
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_COMBAT, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_GENERAL, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_SPELLCASTING, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_AVOIDANCE, new_skill_cap);
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_GENERAL, new_skill_cap);
|
||||
|
||||
if (new_level > player->GetTSLevel())
|
||||
player_skills->SetSkillCapsByType(SKILL_TYPE_HARVESTING, new_skill_cap);
|
||||
|
||||
//SKILL_ID_DUALWIELD, SKILL_ID_FISTS, SKILL_ID_DESTROYING, and SKILL_ID_MAGIC_AFFINITY always have the current_val equal to max_val
|
||||
if (player_skills->HasSkill(SKILL_ID_DUALWIELD))
|
||||
player_skills->SetSkill(SKILL_ID_DUALWIELD, new_skill_cap);
|
||||
if (player_skills->HasSkill(SKILL_ID_FISTS))
|
||||
player_skills->SetSkill(SKILL_ID_FISTS, new_skill_cap);
|
||||
if (player_skills->HasSkill(SKILL_ID_DESTROYING))
|
||||
player_skills->SetSkill(SKILL_ID_DESTROYING, new_skill_cap);
|
||||
if (player_skills->HasSkill(SKILL_ID_MAGIC_AFFINITY))
|
||||
player_skills->SetSkill(SKILL_ID_MAGIC_AFFINITY, new_skill_cap);
|
||||
|
||||
Guild* guild = GetPlayer()->GetGuild();
|
||||
if (guild) {
|
||||
int8 event_type = 0;
|
||||
|
@ -5042,8 +5101,8 @@ void Client::CheckQuestQueue() {
|
|||
for (itr = quest_queue.begin(); itr != quest_queue.end(); itr++) {
|
||||
queued_quest = *itr;
|
||||
SendQuestUpdateStepImmediately(queued_quest->quest, queued_quest->step, queued_quest->display_quest_helper);
|
||||
//if(queued_quest->quest && queued_quest->quest->GetTurnedIn()) //update the journal so the old quest isn't the one displayed in the client's quest helper
|
||||
// SendQuestJournal();
|
||||
if(queued_quest->quest && queued_quest->quest->GetTurnedIn()) //update the journal so the old quest isn't the one displayed in the client's quest helper
|
||||
SendQuestJournal();
|
||||
safe_delete(queued_quest);
|
||||
}
|
||||
quest_queue.clear();
|
||||
|
@ -5320,9 +5379,9 @@ void Client::SendQuestUpdate(Quest* quest) {
|
|||
step = updates->at(i);
|
||||
if (lua_interface && step->Complete() && quest->GetCompleteAction(step->GetStepID()))
|
||||
lua_interface->CallQuestFunction(quest, quest->GetCompleteAction(step->GetStepID()), player);
|
||||
if (step->WasUpdated()) {
|
||||
SendQuestJournal(false, 0, true);
|
||||
if (step->WasUpdated()) {
|
||||
QueuePacket(quest->QuestJournalReply(GetVersion(), GetNameCRC(), player, step));
|
||||
SendQuestJournal(false, 0, true);
|
||||
}
|
||||
LogWrite(CCLIENT__DEBUG, 0, "Client", "Send Quest Journal...");
|
||||
|
||||
|
@ -5384,17 +5443,21 @@ Quest* Client::GetPendingQuestAcceptance(int32 item_id) {
|
|||
MPendingQuestAccept.lock();
|
||||
for (itr = pending_quest_accept.begin(); itr != pending_quest_accept.end(); itr++) {
|
||||
quest = *itr;
|
||||
items = quest->GetSelectableRewardItems();
|
||||
if (items && items->size() > 0) {
|
||||
for (int32 i = 0; i < items->size(); i++) {
|
||||
if (items->at(i)->details.item_id == item_id) {
|
||||
found_quest = true;
|
||||
break;
|
||||
items = quest->GetRewardItems();
|
||||
if (item_id == 0 && items && items->size() > 0) {
|
||||
found_quest = true;
|
||||
}
|
||||
else {
|
||||
items = quest->GetSelectableRewardItems();
|
||||
if (items && items->size() > 0) {
|
||||
for (int32 i = 0; i < items->size(); i++) {
|
||||
if (items->at(i)->details.item_id == item_id) {
|
||||
found_quest = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item_id == 0)
|
||||
found_quest = true;
|
||||
if (found_quest) {
|
||||
pending_quest_accept.erase(itr);
|
||||
break;
|
||||
|
@ -5455,10 +5518,10 @@ void Client::AcceptQuestReward(Quest* quest, int32 item_id) {
|
|||
|
||||
void Client::DisplayQuestRewards(Quest* quest, int64 coin, vector<Item*>* rewards, vector<Item*>* selectable_rewards, map<int32, sint32>* factions, const char* header, int32 status_points, const char* text) {
|
||||
if (coin == 0 && (!rewards || rewards->size() == 0) && (!selectable_rewards || selectable_rewards->size() == 0) && (!factions || factions->size() == 0) && status_points == 0 && text == 0 && (!quest || (quest->GetCoinsReward() == 0 && quest->GetCoinsRewardMax() == 0))) {
|
||||
if (quest)
|
||||
/*if (quest)
|
||||
text = quest->GetName();
|
||||
else
|
||||
return;//nothing to give
|
||||
else*/
|
||||
return;//nothing to give
|
||||
}
|
||||
PacketStruct* packet2 = configReader.getStruct("WS_QuestRewardPackMsg", GetVersion());
|
||||
if (packet2) {
|
||||
|
@ -5478,12 +5541,14 @@ void Client::DisplayQuestRewards(Quest* quest, int64 coin, vector<Item*>* reward
|
|||
if (rewarded_coin > coin)
|
||||
coin = rewarded_coin;
|
||||
if (!quest) { //this entire function is either for version <=546 or for quest rewards in middle of quest, so quest should be 0, otherwise quest will handle the rewards
|
||||
player->AddCoins(coin);
|
||||
PlaySound("coin_cha_ching");
|
||||
if (coin > 0) {
|
||||
player->AddCoins(coin);
|
||||
PlaySound("coin_cha_ching");
|
||||
}
|
||||
}
|
||||
packet2->setSubstructDataByName("reward_data", "unknown1", 255);
|
||||
packet2->setSubstructDataByName("reward_data", "reward", header);
|
||||
packet2->setSubstructDataByName("reward_data", "coin", coin);
|
||||
packet2->setSubstructDataByName("reward_data", "max_coin", coin);
|
||||
if (player->GetGuild()) {
|
||||
if (!quest) { //this entire function is either for version <=546 or for quest rewards in middle of quest, so quest should be 0, otherwise quest will handle the rewards
|
||||
player->GetInfoStruct()->status_points += status_points;
|
||||
|
@ -5694,11 +5759,11 @@ void Client::GiveQuestReward(Quest* quest) {
|
|||
|
||||
quest->IncrementCompleteCount();
|
||||
player->AddCompletedQuest(quest);
|
||||
|
||||
|
||||
DisplayQuestComplete(quest);
|
||||
LogWrite(CCLIENT__DEBUG, 0, "Client", "Send Quest Journal...");
|
||||
SendQuestJournal();
|
||||
player->RemoveQuest(quest->GetQuestID(), false);
|
||||
DisplayQuestComplete(quest);
|
||||
if (quest->GetExpReward() > 0) {
|
||||
int16 level = player->GetLevel();
|
||||
int32 xp = quest->GetExpReward();
|
||||
|
@ -8010,6 +8075,49 @@ void Client::SendIgnoreList() {
|
|||
|
||||
}
|
||||
|
||||
void Client::AddWaypoint(string name, int8 type) {
|
||||
waypoint_id++;
|
||||
WaypointInfo info;
|
||||
info.id = waypoint_id;
|
||||
info.type = type;
|
||||
waypoints[name] = info;
|
||||
}
|
||||
|
||||
void Client::SendWaypoints() {
|
||||
PacketStruct* packet = configReader.getStruct("WS_WaypointUpdate", GetVersion());
|
||||
if (packet) {
|
||||
packet->setArrayLengthByName("num_updates", waypoints.size());
|
||||
map<string, WaypointInfo>::iterator itr;
|
||||
int16 i = 0;
|
||||
for (itr = waypoints.begin(); itr != waypoints.end(); itr++) {
|
||||
packet->setArrayDataByName("waypoint_name", itr->first.c_str(), i);
|
||||
packet->setArrayDataByName("waypoint_category", itr->second.type, i);
|
||||
if(itr->second.type == 3)
|
||||
packet->setArrayDataByName("spawn_id", 0xFFFFFFFF, i);
|
||||
else
|
||||
packet->setArrayDataByName("spawn_id", itr->second.id, i);
|
||||
i++;
|
||||
}
|
||||
QueuePacket(packet->serialize());
|
||||
safe_delete(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::SelectWaypoint(int32 id) {
|
||||
string found_name = "";
|
||||
map<string, WaypointInfo>::iterator itr;
|
||||
for (itr = waypoints.begin(); itr != waypoints.end(); itr++) {
|
||||
if (itr->second.id == id) {
|
||||
found_name = itr->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found_name.length() > 0) {
|
||||
Spawn* spawn = current_zone->FindSpawn(player, found_name.c_str());
|
||||
ShowPathToTarget(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
void Client::AddWaypoint(const char* waypoint_name, int8 waypoint_category, int32 spawn_id) {
|
||||
if (waypoint_name) {
|
||||
PacketStruct* packet = configReader.getStruct("WS_WaypointUpdate", GetVersion());
|
||||
|
@ -8024,7 +8132,37 @@ void Client::AddWaypoint(const char* waypoint_name, int8 waypoint_category, int3
|
|||
safe_delete(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::ShowPathToTarget(Spawn* spawn) {
|
||||
if (spawn && current_zone->pathing) {
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
PathfinderOptions opts;
|
||||
opts.smooth_path = true;
|
||||
opts.step_size = 100.0f;//RuleR(Pathing, NavmeshStepSize);
|
||||
opts.offset = spawn->GetYOffset() + 1.0f;
|
||||
opts.flags = PathingNotDisabled ^ PathingZoneLine;
|
||||
PacketStruct* packet = configReader.getStruct("WS_GlowPath", GetVersion());
|
||||
if (packet) {
|
||||
auto path = current_zone->pathing->FindPath(glm::vec3(player->GetX(), player->GetZ(), player->GetY()), glm::vec3(spawn->GetX(), spawn->GetZ(), spawn->GetY()), partial, stuck, opts);
|
||||
packet->setArrayLengthByName("num_points", path.size());
|
||||
int i = 0;
|
||||
for (auto& node : path)
|
||||
{
|
||||
packet->setArrayDataByName("x", node.pos.x, i);
|
||||
packet->setArrayDataByName("y", node.pos.z, i);
|
||||
packet->setArrayDataByName("z", node.pos.y, i);
|
||||
packet->setDataByName("waypoint_x", spawn->GetX());
|
||||
packet->setDataByName("waypoint_y", spawn->GetY());
|
||||
packet->setDataByName("waypoint_z", spawn->GetZ());
|
||||
i++;
|
||||
}
|
||||
if(i>0)
|
||||
QueuePacket(packet->serialize());
|
||||
safe_delete(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Client::BeginWaypoint(const char* waypoint_name, float x, float y, float z) {
|
||||
|
@ -9065,6 +9203,9 @@ bool Client::HandleNewLogin(int32 account_id, int32 access_code)
|
|||
GetCurrentZone()->AddClient(this); //add to zones client list
|
||||
|
||||
zone_list.AddClientToMap(player->GetName(), this);
|
||||
const char* zone_script = world.GetZoneScript(GetCurrentZone()->GetZoneID());
|
||||
if (zone_script && lua_interface)
|
||||
lua_interface->RunZoneScript(zone_script, "new_client", GetCurrentZone(), GetPlayer());
|
||||
}
|
||||
else {
|
||||
LogWrite(WORLD__ERROR, 0, "World", "Incompatible version: %i", version);
|
||||
|
|
|
@ -134,6 +134,10 @@ struct IncomingPaperdollImage {
|
|||
int8 last_received_packet_index;
|
||||
int8 image_type;
|
||||
};
|
||||
struct WaypointInfo {
|
||||
int32 id;
|
||||
int8 type;
|
||||
};
|
||||
|
||||
class Client {
|
||||
public:
|
||||
|
@ -155,7 +159,7 @@ public:
|
|||
void HandleTellMessage(Client* from, const char* message);
|
||||
void SimpleMessage(int8 color, const char* message);
|
||||
void Message(int8 type, const char* message, ...);
|
||||
void SendSpellUpdate(Spell* spell);
|
||||
void SendSpellUpdate(Spell* spell, bool add_silently = false, bool add_to_hotbar = true);
|
||||
void Zone(ZoneServer* new_zone, bool set_coords = true);
|
||||
void Zone(const char* new_zone, bool set_coords = true);
|
||||
void Zone(int32 zoneid, bool set_coords = true);
|
||||
|
@ -441,6 +445,18 @@ public:
|
|||
void SetRejoinGroupID(int32 id) { rejoin_group_id = id; }
|
||||
|
||||
void TempRemoveGroup();
|
||||
|
||||
void SendWaypoints();
|
||||
|
||||
void AddWaypoint(string name, int8 type);
|
||||
void RemoveWaypoint(string name) {
|
||||
if (waypoints.count(name) > 0){
|
||||
waypoints.erase(name);
|
||||
}
|
||||
}
|
||||
void SelectWaypoint(int32 id);
|
||||
void ShowPathToTarget(Spawn* spawn);
|
||||
|
||||
private:
|
||||
void SavePlayerImages();
|
||||
void SkillChanged(Skill* skill, int16 previous_value, int16 new_value);
|
||||
|
@ -455,6 +471,8 @@ private:
|
|||
Mutex MQuestQueue;
|
||||
Mutex MDeletePlayer;
|
||||
vector<Item*>* search_items;
|
||||
int32 waypoint_id = 0;
|
||||
map<string, WaypointInfo> waypoints;
|
||||
Spawn* transport_spawn;
|
||||
Mutex MBuyBack;
|
||||
deque<BuyBackItem*> buy_back_items;
|
||||
|
|
|
@ -1328,6 +1328,7 @@ bool ZoneServer::Process()
|
|||
database.LoadTransporters(this);
|
||||
LogWrite(TRANSPORT__INFO, 0, "Transport", "-Loading Transporters complete!");
|
||||
reloading = false;
|
||||
world.RemoveReloadingSubSystem("Spawns");
|
||||
}
|
||||
|
||||
MSpawnGroupAssociation.writelock(__FUNCTION__, __LINE__);
|
||||
|
@ -3160,14 +3161,14 @@ void ZoneServer::ClientProcess()
|
|||
}
|
||||
}
|
||||
|
||||
void ZoneServer::SimpleMessage(int8 type, const char* message, Spawn* from, float distance){
|
||||
void ZoneServer::SimpleMessage(int8 type, const char* message, Spawn* from, float distance, bool send_to_sender){
|
||||
Client* client = 0;
|
||||
vector<Client*>::iterator client_itr;
|
||||
|
||||
MClientList.readlock(__FUNCTION__, __LINE__);
|
||||
for (client_itr = clients.begin(); client_itr != clients.end(); client_itr++) {
|
||||
client = *client_itr;
|
||||
if(from && client && client->IsConnected() && from->GetDistance(client->GetPlayer()) <= distance){
|
||||
if(from && client && client->IsConnected() && (send_to_sender || from != client->GetPlayer()) && from->GetDistance(client->GetPlayer()) <= distance){
|
||||
client->SimpleMessage(type, message);
|
||||
}
|
||||
}
|
||||
|
@ -4856,6 +4857,23 @@ void ZoneServer::StartZoneInitialSpawnThread(Client* client){
|
|||
}
|
||||
|
||||
void ZoneServer::SendZoneSpawns(Client* client){
|
||||
int8 count = 0;
|
||||
while (LoadingData && count <= 6000) { //sleep for max of 60 seconds (60000ms) while the maps are loading
|
||||
count++;
|
||||
Sleep(10);
|
||||
}
|
||||
count = 0;
|
||||
int16 size = 0;
|
||||
//give the spawn thread a tad bit of time to add the pending_spawns to spawn_list (up to 10 seconds)
|
||||
while (count < 1000) {
|
||||
MPendingSpawnListAdd.readlock(__FUNCTION__, __LINE__);
|
||||
size = pending_spawn_list_add.size();
|
||||
MPendingSpawnListAdd.releasereadlock(__FUNCTION__, __LINE__);
|
||||
if (size == 0)
|
||||
break;
|
||||
Sleep(10);
|
||||
count++;
|
||||
}
|
||||
initial_spawn_threads_active++;
|
||||
|
||||
map<int32, Spawn*>::iterator itr;
|
||||
|
@ -7492,6 +7510,7 @@ void ZoneServer::ReloadSpawns() {
|
|||
return;
|
||||
|
||||
reloading = true;
|
||||
world.SetReloadingSubsystem("Spawns");
|
||||
// Let every one in the zone know what is happening
|
||||
HandleBroadcast("Reloading all spawns for this zone.");
|
||||
DeleteGlobalSpawns();
|
||||
|
|
|
@ -275,7 +275,7 @@ public:
|
|||
|
||||
void AddClient(Client* client);
|
||||
|
||||
void SimpleMessage(int8 type, const char* message, Spawn* from, float distance);
|
||||
void SimpleMessage(int8 type, const char* message, Spawn* from, float distance, bool send_to_sender = true);
|
||||
void HandleChatMessage(Spawn* from, const char* to, int16 channel, const char* message, float distance = 0, const char* channel_name = 0, bool show_bubble = true, int32 language = 0);
|
||||
void HandleChatMessage(Client* client, Spawn* from, const char* to, int16 channel, const char* message, float distance = 0, const char* channel_name = 0, bool show_bubble = true, int32 language = 0);
|
||||
void HandleBroadcast(const char* message);
|
||||
|
|
|
@ -237,7 +237,9 @@ void ConfigReader::loadDataStruct(PacketStruct* packet, XMLNode parentNode, bool
|
|||
ds2->SetIfNotEqualsVariable(ds->GetIfNotEqualsVariable());
|
||||
ds2->SetIfFlagNotSetVariable(ds->GetIfFlagNotSetVariable());
|
||||
ds2->SetIfFlagSetVariable(ds->GetIfFlagSetVariable());
|
||||
ds2->SetIsOptional(ds->IsOptional());
|
||||
ds2->SetIsOptional(ds->IsOptional());
|
||||
ds2->AddIfSetVariable(if_variable); //add this if the modifier is on the piece that is including the substruct
|
||||
ds2->AddIfNotSetVariable(if_not_variable); //add this if the modifier is on the piece that is including the substruct
|
||||
packet->add(ds2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -351,6 +351,25 @@ int8 DataStruct::GetAddType() {
|
|||
void DataStruct::SetAddType(int8 new_type) {
|
||||
addType = new_type;
|
||||
}
|
||||
string DataStruct::AppendVariable(string orig, const char* val) {
|
||||
if (!val)
|
||||
return orig;
|
||||
if(orig.length() == 0)
|
||||
return string(val);
|
||||
if (orig.find(",") < 0xFFFFFFFF) { //has more than one already
|
||||
string valstr = string(val);
|
||||
vector<string>* varnames = SplitString(orig, ',');
|
||||
if (varnames) {
|
||||
for (int32 i = 0; i < varnames->size(); i++) {
|
||||
if (valstr.compare(varnames->at(i)) == 0) {
|
||||
return orig; //already in the variable, no need to append
|
||||
}
|
||||
}
|
||||
safe_delete(varnames);
|
||||
}
|
||||
}
|
||||
return orig.append(",").append(val);
|
||||
}
|
||||
int32 DataStruct::GetDataSizeInBytes() {
|
||||
int32 ret = 0;
|
||||
switch (type) {
|
||||
|
|
|
@ -113,6 +113,19 @@ public:
|
|||
bool IsSet();
|
||||
bool IsOptional();
|
||||
int32 GetDataSizeInBytes();
|
||||
string AppendVariable(string orig, const char* val);
|
||||
void AddIfSetVariable(const char* val) {
|
||||
if (val) {
|
||||
if_set_variable = AppendVariable(if_set_variable, val);
|
||||
is_set = true;
|
||||
}
|
||||
}
|
||||
void AddIfNotSetVariable(const char* val) {
|
||||
if (val) {
|
||||
if_not_set_variable = AppendVariable(if_not_set_variable, val);
|
||||
if_not_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_set;
|
||||
|
|
|
@ -283,6 +283,13 @@ bool alpha_check(unsigned char val){
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned int GetSpellNameCrc(const char* src) {
|
||||
if (!src)
|
||||
return 0;
|
||||
uLong crc = crc32(0L, Z_NULL, 0);
|
||||
return crc32(crc, (unsigned const char*)src, strlen(src));
|
||||
}
|
||||
|
||||
int GetItemNameCrc(string item_name){
|
||||
const char *src = item_name.c_str();
|
||||
uLong crc = crc32(0L, Z_NULL, 0);
|
||||
|
|
|
@ -59,6 +59,7 @@ string timestamp(time_t now=0);
|
|||
string long2ip(unsigned long ip);
|
||||
string pop_arg(string &s, string seps, bool obey_quotes);
|
||||
int EQsprintf(char *buffer, const char *pattern, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5, const char *arg6, const char *arg7, const char *arg8, const char *arg9);
|
||||
unsigned int GetSpellNameCrc(const char* src);
|
||||
int GetItemNameCrc(string item_name);
|
||||
unsigned int GetNameCrc(string name);
|
||||
#endif
|
||||
|
|
|
@ -520,7 +520,7 @@
|
|||
<Data ElementName="bump_size" Type="sint8" Size="1" /> <!-- 604 -->
|
||||
<Data ElementName="soga_skull_type" Type="sint8" Size="3" /> <!-- 605 -->
|
||||
<Data ElementName="soga_eye_type" Type="sint8" Size="3" /> <!-- 608 -->
|
||||
<Data ElementName="ear_type" Type="sint8" Size="3" /> <!-- 611 -->
|
||||
<Data ElementName="soga_ear_type" Type="sint8" Size="3" /> <!-- 611 -->
|
||||
<Data ElementName="soga_eye_brow_type" Type="sint8" Size="3" /> <!-- 614 -->
|
||||
<Data ElementName="soga_cheek_type" Type="sint8" Size="3" /> <!-- 617 -->
|
||||
<Data ElementName="soga_lip_type" Type="sint8" Size="3" /> <!-- 620 -->
|
||||
|
|
|
@ -407,6 +407,14 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="hour" Type="int8" Size="1" />
|
||||
<Data ElementName="minute" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_GameWorldTime" ClientVersion="547" OpcodeName="OP_GameWorldTimeMsg">
|
||||
<Data ElementName="year" Type="int16" Size="1" />
|
||||
<Data ElementName="month" Type="int8" Size="1" />
|
||||
<Data ElementName="day" Type="int8" Size="1" />
|
||||
<Data ElementName="hour" Type="int8" Size="1" />
|
||||
<Data ElementName="minute" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown" Type="int8" Size="1" />
|
||||
<Data ElementName="unix_time" Type="int32" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_GameWorldTime" ClientVersion="1193" OpcodeName="OP_GameWorldTimeMsg">
|
||||
|
@ -422,6 +430,10 @@ to zero and treated like placeholders." />
|
|||
<Struct Name="WS_Camp" ClientVersion="1" OpcodeName="OP_CampStartedMsg" >
|
||||
<Data ElementName="seconds" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_desktop" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_Camp" ClientVersion="547" OpcodeName="OP_CampStartedMsg" >
|
||||
<Data ElementName="seconds" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_desktop" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_char_select" Type="int8" Size="1" />
|
||||
<Data ElementName="char_name" Type="EQ2_16Bit_String" />
|
||||
<Data ElementName="unknown" Type="int8" Size="3" />
|
||||
|
@ -433,7 +445,11 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="char_name" Type="EQ2_16Bit_String" />
|
||||
<Data ElementName="unknown" Type="int8" Size="8" />
|
||||
</Struct>
|
||||
<Struct Name="WS_RequestCamp" ClientVersion="1" OpcodeName="OP_RequestCampMsg">
|
||||
<Struct Name="WS_RequestCamp" ClientVersion="" OpcodeName="OP_RequestCampMsg">
|
||||
<Data ElementName="quit" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_desktop" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_RequestCamp" ClientVersion="547" OpcodeName="OP_RequestCampMsg">
|
||||
<Data ElementName="quit" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_desktop" Type="int8" Size="1" />
|
||||
<Data ElementName="camp_char_select" Type="int16" Size="1" />
|
||||
|
@ -459,8 +475,8 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="spell_id" Type="int32" Size="1" />
|
||||
<Data ElementName="unique_id" Type="int32" Size="1" />
|
||||
<Data ElementName="spell_name" Type="EQ2_16Bit_String" />
|
||||
<Data ElementName="display_spell_tier" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int8" Size="1" />
|
||||
<Data ElementName="add_silently" Type="int8" Size="1" />
|
||||
<Data ElementName="add_to_hotbar" Type="int8" Size="1" />
|
||||
<Data ElementName="tier" Type="int8" Size="1" />
|
||||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
<Data ElementName="icon_type" Type="int16" Size="1" />
|
||||
|
@ -501,6 +517,18 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
</Data>
|
||||
</Struct>
|
||||
<Struct Name="WS_MacroInit" ClientVersion="546" OpcodeName="OP_MacroInitMsg" >
|
||||
<Data ElementName="macro_count" Type="int32" />
|
||||
<Data ElementName="macro_array" Type="Array" ArraySizeVariable="macro_count">
|
||||
<Data ElementName="number" Type="int8" />
|
||||
<Data ElementName="name" Type="EQ2_8Bit_String" />
|
||||
<Data ElementName="macro_details_count" Type="int8" />
|
||||
<Data ElementName="macro_details_array" Type="Array" ArraySizeVariable="macro_details_count">
|
||||
<Data ElementName="command" Type="EQ2_16Bit_String" />
|
||||
</Data>
|
||||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
</Data>
|
||||
</Struct>
|
||||
<Struct Name="WS_MacroInit" ClientVersion="547" OpcodeName="OP_MacroInitMsg" >
|
||||
<Data ElementName="macro_count" Type="int32" />
|
||||
<Data ElementName="macro_array" Type="Array" ArraySizeVariable="macro_count">
|
||||
|
@ -1335,12 +1363,12 @@ to zero and treated like placeholders." />
|
|||
</Struct>
|
||||
<Struct Name="Substruct_SpellEffects" ClientVersion="546" >
|
||||
<Data ElementName="spell_id" Type="int32" Size="1" />
|
||||
<Data ElementName="cancellable" Type="int8" Size="1" />
|
||||
<Data ElementName="total_time" Type="float" Size="1" />
|
||||
<Data ElementName="expire_timestamp" Type="int32" Size="1" />
|
||||
<Data ElementName="unknown2" Type="int8" Size="1" />
|
||||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
<Data ElementName="icon_type" Type="int16" Size="1" />
|
||||
<Data ElementName="unknown2" Type="int8" Size="1" />
|
||||
<Data ElementName="cancellable" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="Substruct_SpellEffects" ClientVersion="843" >
|
||||
|
@ -3184,7 +3212,7 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="language_unknown" Type="int8" Size="1" />
|
||||
</Data>
|
||||
</Struct>
|
||||
<Struct Name="WS_UpdateSkillBook" ClientVersion="547" OpcodeName="OP_UpdateSkillBookMsg" >
|
||||
<Struct Name="WS_UpdateSkillBook" ClientVersion="865" OpcodeName="OP_UpdateSkillBookMsg" >
|
||||
<Data ElementName="skill_count" Type="int16" />
|
||||
<Data ElementName="packed_size" Type="int32" />
|
||||
<Data ElementName="unknown" Type="int8" />
|
||||
|
@ -3281,15 +3309,16 @@ to zero and treated like placeholders." />
|
|||
</Struct>
|
||||
<Struct Name="SubStruct_UpdateSpellBook" ClientVersion="546">
|
||||
<Data ElementName="spell_id" Type="int32" />
|
||||
<Data ElementName="unique_id" Type="int32" />
|
||||
<Data ElementName="recast_available" Type="int32" Size="1" />
|
||||
<Data ElementName="type" Type="int16" Size="1" />
|
||||
<Data ElementName="recast_time" Type="int16" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int16" />
|
||||
<Data ElementName="unique_id" Type="int32" />
|
||||
<Data ElementName="recast_available" Type="int32" Size="1" />
|
||||
<Data ElementName="type" Type="int8" Size="1" />
|
||||
<Data ElementName="recast_time" Type="int16" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int8" />
|
||||
<Data ElementName="unknown4" Type="int16" />
|
||||
<Data ElementName="icon" Type="sint16" />
|
||||
<Data ElementName="icon_type" Type="int16" />
|
||||
<Data ElementName="icon2" Type="int16" Size="1" />
|
||||
<Data ElementName="charges" Type="int8" Size="1" />
|
||||
<Data ElementName="icon2" Type="int16" Size="1" />
|
||||
<Data ElementName="charges" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown5" Type="int8" Size="1" />
|
||||
<Data ElementName="status" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
|
@ -4721,6 +4750,14 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="name" Type="EQ2_8Bit_String" Size="1" />
|
||||
<Data ElementName="description" Type="EQ2_16Bit_String" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_EffectInfo" ClientVersion="546">
|
||||
<Data ElementName="id" Type="int32" />
|
||||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
<Data ElementName="icontype" Type="int16" Size="1" />
|
||||
<Data ElementName="type" Type="int16" Size="1" /> <!-- spell=0, combat_art=1, ability=2 -->
|
||||
<Data ElementName="name" Type="EQ2_8Bit_String" Size="1" />
|
||||
<Data ElementName="description" Type="EQ2_16Bit_String" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_PartialSpellInfo" ClientVersion="1">
|
||||
<Data ElementName="id" Type="int32" />
|
||||
<Data ElementName="icon" Type="int16" Size="1" />
|
||||
|
@ -6092,6 +6129,10 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="info_header" Substruct="WS_ExamineInfoHeader" Size="1" />
|
||||
<Data ElementName="spell_info" Substruct="WS_EffectInfo" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_ExamineEffectInfo" ClientVersion="546" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqExamineInfoCmd">
|
||||
<Data ElementName="info_header" Substruct="WS_ExamineInfoHeader" Size="1" />
|
||||
<Data ElementName="spell_info" Substruct="WS_EffectInfo" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_ExaminePartialSpellInfo" ClientVersion="1" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqExamineInfoCmd">
|
||||
<Data ElementName="info_header" Substruct="WS_ExamineInfoHeader" Size="1" />
|
||||
<Data ElementName="spell_info" Substruct="WS_PartialSpellInfo" Size="1" />
|
||||
|
@ -6661,7 +6702,7 @@ to zero and treated like placeholders." />
|
|||
<Struct Name="Substruct_JournalRewardData" ClientVersion="546">
|
||||
<Data ElementName="unknown1" Type="int8" Size="1" /> <!-- 255=quest reward, 0=enemy mastery, 1=specialized training,2=character trait, 3=racial tradition -->
|
||||
<Data ElementName="reward" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="coin" Type="int64" Size="1" />
|
||||
<Data ElementName="max_coin" Type="int64" Size="1" />
|
||||
<Data ElementName="min_coin" Type="int64" Size="1" />
|
||||
<Data ElementName="status_points" Type="int32" Size="1" />
|
||||
<Data ElementName="text" Type="EQ2_16Bit_String" Size="1" />
|
||||
|
@ -6911,7 +6952,7 @@ to zero and treated like placeholders." />
|
|||
</Data>
|
||||
<Data ElementName="unknown10" Type="int8" />
|
||||
</Struct>
|
||||
<Struct Name="WS_WhoQueryReply" ClientVersion="547" OpcodeName="OP_WhoQueryReplyMsg" >
|
||||
<Struct Name="WS_WhoQueryReply" ClientVersion="546" OpcodeName="OP_WhoQueryReplyMsg" >
|
||||
<Data ElementName="account_id" Type="int32" />
|
||||
<Data ElementName="unknown" Type="int32" />
|
||||
<Data ElementName="response" Type="int8" />
|
||||
|
@ -7147,7 +7188,7 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="name" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="quest_type" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="quest_zone" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="unknown1" Type="int8" Size="1" />
|
||||
<Data ElementName="journal_updated" Type="int8" Size="1" />
|
||||
<Data ElementName="turned_in" Type="int8" Size="1" />
|
||||
<Data ElementName="repeatable" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown2" Type="int8" Size="1" />
|
||||
|
@ -7175,7 +7216,7 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="name" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="quest_type" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="quest_zone" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="unknown1" Type="int8" Size="1" />
|
||||
<Data ElementName="journal_updated" Type="int8" Size="1" />
|
||||
<Data ElementName="turned_in" Type="int8" Size="1" />
|
||||
<Data ElementName="repeatable" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown2" Type="int8" Size="1" />
|
||||
|
@ -7514,6 +7555,14 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="unknown" Type="int8" Size="1" />
|
||||
</Struct>
|
||||
<Struct Name="WS_WaypointUpdate" ClientVersion="1" OpcodeName="OP_WaypointUpdateMsg">
|
||||
<Data ElementName="num_updates" Type="int32" />
|
||||
<Data ElementName="update_array" Type="Array" ArraySizeVariable="num_updates">
|
||||
<Data ElementName="waypoint_name" Type="EQ2_16Bit_string" />
|
||||
<Data ElementName="waypoint_category" Type="int8" />
|
||||
<Data ElementName="spawn_id" Type="int32" />
|
||||
</Data>
|
||||
</Struct>
|
||||
<Struct Name="WS_WaypointUpdate" ClientVersion="547" OpcodeName="OP_WaypointUpdateMsg">
|
||||
<Data ElementName="num_updates" Type="int32" />
|
||||
<Data ElementName="update_array" Type="Array" ArraySizeVariable="num_updates">
|
||||
<Data ElementName="waypoint_name" Type="EQ2_16Bit_string" />
|
||||
|
@ -7524,6 +7573,9 @@ to zero and treated like placeholders." />
|
|||
</Data>
|
||||
</Struct>
|
||||
<Struct Name="WS_WaypointSelect" ClientVersion="1" OpcodeName="OP_WaypointSelectMsg">
|
||||
<Data ElementName="selection" Type="int32" />
|
||||
</Struct>
|
||||
<Struct Name="WS_WaypointSelect" ClientVersion="547" OpcodeName="OP_WaypointSelectMsg">
|
||||
<Data ElementName="num_selections" Type="int32" />
|
||||
<Data ElementName="selection_array" Type="Array" ArraySizeVariable="num_selections">
|
||||
<Data ElementName="waypoint_name" Type="EQ2_16Bit_string" />
|
||||
|
@ -7586,11 +7638,19 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="month" Type="int8" Size="1" />
|
||||
<Data ElementName="year" Type="int8" Size="1" />
|
||||
<Data ElementName="time_obtained" Type="int32" Size="1" />
|
||||
<Data ElementName="unknown" Type="int8" Size="4" />
|
||||
<Data ElementName="timer_duration" Type="int16" Size="1" />
|
||||
<Data ElementName="timer_running" Type="int8" Size="1" /> <!-- start timer counting up -->
|
||||
<Data ElementName="timer_countdown" Type="int8" Size="1" /> <!-- count down instead of counting up -->
|
||||
<Data ElementName="level" Type="int8" Size="1" />
|
||||
<Data ElementName="encounter_level" Type="int8" Size="1" />
|
||||
<Data ElementName="difficulty" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int8" Size="8" />
|
||||
<Data ElementName="complete" Type="int8" Size="1" />
|
||||
<Data ElementName="complete2" Type="int8" Size="1" />
|
||||
<Data ElementName="complete3" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown3" Type="int8" Size="2" />
|
||||
<Data ElementName="deletable" Type="int8" Size="1" />
|
||||
<Data ElementName="shareable" Type="int8" Size="1" />
|
||||
<Data ElementName="unknown3b" Type="int8" Size="1" />
|
||||
<Data ElementName="task_groups_completed" Type="int16" Size="1" />
|
||||
<Data ElementName="num_task_groups" Type="int16" />
|
||||
<Data ElementName="task_group_array" Type="Array" ArraySizeVariable="num_task_groups">
|
||||
|
@ -7621,7 +7681,7 @@ to zero and treated like placeholders." />
|
|||
<Data ElementName="onscreen_update_text2" Type="EQ2_16Bit_String" Size="1" />
|
||||
<Data ElementName="onscreen_update_icon" Type="int16" Size="1" />
|
||||
<Data ElementName="unknown6" Type="int8" Size="1" />
|
||||
<Data ElementName="reward_data" Substruct="Substruct_JournalRewardData" Optional="true" />
|
||||
<Data ElementName="reward_data" Substruct="Substruct_JournalRewardData" IfVariableNotSet="complete" />
|
||||
</Struct>
|
||||
<Struct Name="WS_QuestJournalReply" ClientVersion="547" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqQuestJournalReplyCmd" >
|
||||
<Data ElementName="quest_id" Type="int32" Size="1" />
|
||||
|
@ -18197,6 +18257,27 @@ to zero and treated like placeholders." />
|
|||
</Struct>
|
||||
<Struct Name="WS_SatMsg" ClientVersion="1" OpcodeName="OP_SatMsg">
|
||||
</Struct>
|
||||
<Struct Name="WS_KnowledgebaseRequestMsg" ClientVersion="1" OpcodeName="OP_KnowledgebaseRequestMsg">
|
||||
<Data ElementName="request_id" Type="int32" />
|
||||
<Data ElementName="search_keyword" Type="EQ2_16Bit_String" />
|
||||
<Data ElementName="search_article" Type="EQ2_16Bit_String" />
|
||||
</Struct>
|
||||
<Struct Name="WS_KnowledgebaseResponseMsg" ClientVersion="1" OpcodeName="OP_KnowledgebaseResponseMsg">
|
||||
<Data ElementName="unknown" Type="int8" Size="6" />
|
||||
<Data ElementName="num_articles" Type="int16" />
|
||||
<Data ElementName="article_array" Type="Array" ArraySizeVariable="num_articles">
|
||||
<Data ElementName="article" Type="EQ2_16Bit_String" />
|
||||
</Data>
|
||||
<Data ElementName="num_match_percents2" Type="int16" />
|
||||
<Data ElementName="match_percents_array" Type="Array" ArraySizeVariable="num_match_percents">
|
||||
<Data ElementName="percentage" Type="int16" />
|
||||
</Data>
|
||||
<Data ElementName="num_article_summaries" Type="int16" />
|
||||
<Data ElementName="article_summaries_array" Type="Array" ArraySizeVariable="num_article_summaries">
|
||||
<Data ElementName="summary" Type="EQ2_16Bit_String" />
|
||||
</Data>
|
||||
<Data ElementName="article" Type="EQ2_16Bit_String" />
|
||||
</Struct>
|
||||
<Struct Name="WS_SysClient" ClientVersion="1" OpcodeName="OP_SysClient">
|
||||
<Data ElementName="sys_client" Type="EQ2_16Bit_String" />
|
||||
</Struct>
|
||||
|
|
Loading…
Reference in a new issue