Timers and some more loading stuff

This commit is contained in:
KimLS 2015-06-20 19:44:00 -07:00
parent 635ac692ea
commit d5098a56e0
18 changed files with 199 additions and 79 deletions

View File

@ -150,4 +150,26 @@ static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
}
}
static uint32 ExpansionFromClientVersion(ClientVersion clientVersion)
{
switch(clientVersion)
{
case ClientVersion::Unknown:
case ClientVersion::Client62:
case ClientVersion::Titanium:
return 0x000007FFU;
case ClientVersion::SoF:
return 0x00007FFFU;
case ClientVersion::SoD:
return 0x0000FFFFU;
case ClientVersion::UF:
return 0x0001FFFFU;
case ClientVersion::RoF:
case ClientVersion::RoF2:
return 0x000FFFFFU;
default:
return 0;
}
}
#endif /* CLIENTVERSIONS_H */

View File

@ -184,6 +184,7 @@ RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against Ant
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method.
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.

View File

@ -152,7 +152,13 @@ void Client::SendEnterWorld(std::string name)
void Client::SendExpansionInfo() {
auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct));
ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer;
eis->Expansions = (RuleI(World, ExpansionSettings));
if(RuleB(World, UseClientBasedExpansionSettings)) {
eis->Expansions = ExpansionFromClientVersion(eqs->GetClientVersion());
//eis->Expansions = ExpansionFromClientVersion(this->GetCLE.
} else {
eis->Expansions = (RuleI(World, ExpansionSettings));
}
QueuePacket(outapp);
safe_delete(outapp);
}

View File

@ -872,8 +872,8 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) {
}
for(auto &prereq : rank->prereqs) {
outapp->WriteSInt32(prereq.aa_id);
outapp->WriteSInt32(prereq.points);
outapp->WriteSInt32(prereq.first);
outapp->WriteSInt32(prereq.second);
}
QueuePacket(outapp);
@ -948,6 +948,41 @@ void Client::SendAlternateAdvancementTimers() {
safe_delete(outapp);
}
void Client::ResetAlternateAdvancementTimer(int ability) {
AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id);
if(rank) {
SendAlternateAdvancementTimer(rank->spell_type, 0, time(0));
p_timers.Clear(&database, rank->spell_type + pTimerAAStart);
}
}
void Client::ResetAlternateAdvancementTimers() {
EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct));
UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer;
PTimerList::iterator c, e;
c = p_timers.begin();
e = p_timers.end();
std::vector<int> r_timers;
for(; c != e; ++c) {
PersistentTimer *cur = c->second;
if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd)
continue;
//send timer
uaaout->begin = 0;
uaaout->end = static_cast<uint32>(time(nullptr));
uaaout->ability = cur->GetType() - pTimerAAStart;
r_timers.push_back(cur->GetType());
QueuePacket(outapp);
}
for(auto &i : r_timers) {
p_timers.Clear(&database, i);
}
safe_delete(outapp);
}
void Client::PurchaseAlternateAdvancementRank(int rank_id) {
AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id);
if(!rank) {
@ -1212,13 +1247,13 @@ void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) {
bool ZoneDatabase::LoadAlternateAdvancement(Client *c) {
c->ClearAAs();
std::string query = StringFormat(
"SELECT "
"aa_id, "
"aa_value, "
"charges "
"FROM "
"`character_alternate_abilities` "
"WHERE `id` = %u ORDER BY `slot`", c->CharacterID());
"SELECT "
"aa_id, "
"aa_value, "
"charges "
"FROM "
"`character_alternate_abilities` "
"WHERE `id` = %u", c->CharacterID());
MySQLRequestResult results = database.QueryDatabase(query);
int i = 0;
@ -1227,11 +1262,25 @@ bool ZoneDatabase::LoadAlternateAdvancement(Client *c) {
uint32 value = atoi(row[1]);
uint32 charges = atoi(row[2]);
c->GetPP().aa_array[i].AA = aa;
c->GetPP().aa_array[i].value = value;
c->GetPP().aa_array[i].charges = charges;
c->SetAA(aa, value, charges);
i++;
auto rank = zone->GetAlternateAdvancementRank(aa);
if(!rank) {
continue;
}
auto ability = rank->base_ability;
if(!ability) {
continue;
}
rank = ability->GetRankByPointsSpent(value);
if(c->CanUseAlternateAdvancementRank(rank)) {
c->GetPP().aa_array[i].AA = aa;
c->GetPP().aa_array[i].value = value;
c->GetPP().aa_array[i].charges = charges;
c->SetAA(aa, value, charges);
i++;
}
}
return true;
@ -1359,8 +1408,14 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
}
}
if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) {
return false;
if(IsClient()) {
if(!(CastToClient()->GetPP().expansions & (1 << rank->expansion))) {
return false;
}
} else {
if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) {
return false;
}
}
auto race = GetArrayRace(GetBaseRace());
@ -1427,11 +1482,11 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price)
//check prereqs
for(auto &prereq : rank->prereqs) {
AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.aa_id);
AA::Ability *prereq_ability = zone->GetAlternateAdvancementAbility(prereq.first);
if(prereq_ability) {
auto ranks = GetAA(prereq_ability->first_rank_id);
if(ranks < prereq.points) {
if(ranks < prereq.second) {
return false;
}
}
@ -1473,6 +1528,24 @@ void Zone::LoadAlternateAdvancement() {
if(current->prev) {
current->total_cost = current->cost + current->prev->total_cost;
//check prereqs here
for(auto &prev_prereq : current->prev->prereqs) {
// //if prev has an aa we dont have set
// // then set it here too
// //if prev has an aa we have and the count is different
// // then set to whichever is highest
//
auto iter = current->prereqs.find(prev_prereq.first);
if(iter == current->prereqs.end()) {
//not found
current->prereqs[prev_prereq.first] = prev_prereq.second;
} else {
//they already have it too!
auto points = std::max(iter->second, prev_prereq.second);
current->prereqs[iter->first] = points;
}
}
}
else {
current->prev_id = -1;
@ -1593,14 +1666,17 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
results = QueryDatabase(query);
if(results.Success()) {
for(auto row = results.begin(); row != results.end(); ++row) {
AA::RankPrereq prereq;
int rank_id = atoi(row[0]);
prereq.aa_id = atoi(row[1]);
prereq.points = atoi(row[2]);
int aa_id = atoi(row[1]);
int points = atoi(row[2]);
if(aa_id <= 0 || points <= 0) {
continue;
}
if(ranks.count(rank_id) > 0) {
AA::Rank *rank = ranks[rank_id].get();
rank->prereqs.push_back(prereq);
rank->prereqs[aa_id] = points;
}
}
} else {
@ -1650,4 +1726,4 @@ void Mob::GrantAlternateAdvancementAbility(int aa_id, int points) {
c->SendAlternateAdvancementStats();
c->CalcBonuses();
}
}
}

View File

@ -1536,4 +1536,11 @@ public:
uint32 owner_id;
};
enum AATimers
{
aaTimerRampage,
aaTimerWarcry,
aaTimerMax
};
#endif

View File

@ -24,7 +24,6 @@
#include <vector>
#include <memory>
#include "aa_rank_effects.h"
#include "aa_rank_prereqs.h"
#include "aa_rank.h"
class Mob;

View File

@ -48,7 +48,7 @@ public:
int total_cost;
Ability *base_ability;
std::vector<RankEffect> effects;
std::vector<RankPrereq> prereqs;
std::map<int, int> prereqs;
};
}

View File

@ -1,33 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_RANK_PREREQS_H
#define EQEMU_ZONE_AA_RANK_PREREQS_H
namespace AA
{
struct RankPrereq
{
int aa_id;
int points;
};
}
#endif

View File

@ -524,7 +524,6 @@ void Client::ReportConnectingState() {
}
bool Client::SaveAA() {
std::string dquery;
std::string iquery;
int spentpoints = 0;
int i = 0;
@ -546,10 +545,10 @@ bool Client::SaveAA() {
spentpoints += r->total_cost;
if(i == 0) {
iquery = StringFormat("INSERT INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)"
" VALUES (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second);
iquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value, charges)"
" VALUES (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
} else {
iquery += StringFormat(", (%u, %u, %u, %u, %u)", character_id, i, ability->first_rank_id, rank.second.first, rank.second.second);
iquery += StringFormat(", (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
}
i++;
}
@ -557,9 +556,6 @@ bool Client::SaveAA() {
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
dquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE id=%u", character_id);
database.QueryDatabase(dquery);
if(iquery.length() > 0) {
database.QueryDatabase(iquery);
}

View File

@ -45,7 +45,6 @@ struct Item_Struct;
#include "../common/item_struct.h"
#include "../common/clientversions.h"
#include "aa.h"
#include "common.h"
#include "merc.h"
#include "mob.h"
@ -768,6 +767,8 @@ public:
void SendAlternateAdvancementPoints();
void SendAlternateAdvancementTimer(int ability, int begin, int end);
void SendAlternateAdvancementTimers();
void ResetAlternateAdvancementTimer(int ability);
void ResetAlternateAdvancementTimers();
void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); }
void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); }

View File

@ -1440,6 +1440,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; }
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; }
if(RuleB(World, UseClientBasedExpansionSettings)) {
m_pp.expansions = ExpansionFromClientVersion(GetClientVersion());
}
else {
m_pp.expansions = RuleI(World, ExpansionSettings);
}
if(!database.LoadAlternateAdvancement(this)) {
Log.Out(Logs::General, Logs::Error, "Error loading AA points for %s", GetName());
}
@ -1566,9 +1573,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* Update LFP in case any (or all) of our group disbanded while we were zoning. */
if (IsLFP()) { UpdateLFP(); }
/* Get Expansions from variables table and ship via PP */
m_pp.expansions = RuleI(World, ExpansionSettings);
p_timers.SetCharID(CharacterID());
if (!p_timers.Load(&database)) {
Log.Out(Logs::General, Logs::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID());

View File

@ -320,6 +320,7 @@ int command_init(void) {
command_add("raidloot", "LEADER|GROUPLEADER|SELECTED|ALL - Sets your raid loot settings if you have permission to do so.", 0, command_raidloot) ||
command_add("randomfeatures", "- Temporarily randomizes the Facial Features of your target", 80, command_randomfeatures) ||
command_add("refreshgroup", "- Refreshes Group.", 0, command_refreshgroup) ||
command_add("reloadaa", "Reloads AA data", 200, command_reloadaa) ||
command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) ||
command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) ||
command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) ||
@ -333,6 +334,7 @@ int command_init(void) {
command_add("reloadzps", nullptr,0, command_reloadzps) ||
command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) ||
command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) ||
command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) ||
command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) ||
command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) ||
command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) ||
@ -10580,3 +10582,35 @@ void command_mysqltest(Client *c, const Seperator *sep)
}
Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
}
void command_resetaa_timer(Client *c, const Seperator *sep) {
Client *target = nullptr;
if(!c->GetTarget() || !c->GetTarget()->IsClient()) {
target = c;
} else {
target = c->GetTarget()->CastToClient();
}
if(sep->IsNumber(1))
{
int timer_id = atoi(sep->arg[1]);
c->Message(0, "Reset of timer %i for %s", timer_id, c->GetName());
c->ResetAlternateAdvancementTimer(timer_id);
}
else if(!strcasecmp(sep->arg[1], "all"))
{
c->Message(0, "Reset all timers for %s", c->GetName());
c->ResetAlternateAdvancementTimers();
}
else
{
c->Message(0, "usage: #resetaa_timer [all | timer_id]");
}
}
void command_reloadaa(Client *c, const Seperator *sep) {
c->Message(0, "Reloading Alternate Advancement Data...");
zone->LoadAlternateAdvancement();
c->Message(0, "Alternate Advancement Data Reloaded");
entity_list.SendAlternateAdvancementStats();
}

View File

@ -323,7 +323,9 @@ void command_tune(Client *c, const Seperator *sep);
void command_logtest(Client *c, const Seperator *sep);
void command_mysqltest(Client *c, const Seperator *sep);
void command_logs(Client *c, const Seperator *sep);
void command_resetaa_timer(Client *c, const Seperator *sep);
void command_reloadaa(Client *c, const Seperator *sep);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);
void command_profilereset(Client *c, const Seperator *sep);

View File

@ -4704,3 +4704,11 @@ void EntityList::StopMobAI()
mob.second->AI_ShutDown();
}
}
void EntityList::SendAlternateAdvancementStats() {
for(auto &c : client_list) {
c.second->SendAlternateAdvancementTable();
c.second->SendAlternateAdvancementStats();
c.second->SendAlternateAdvancementPoints();
}
}

View File

@ -398,7 +398,6 @@ public:
void SaveAllClientsTaskState();
void ReloadAllClientsTaskState(int TaskID=0);
uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0);
uint16 CreateDoor(const char *model, const glm::vec4& position, uint8 type = 0, uint16 size = 100);
@ -429,6 +428,7 @@ public:
uint16 GetFreeID();
void RefreshAutoXTargets(Client *c);
void RefreshClientXTargets(Client *c);
void SendAlternateAdvancementStats();
protected:
friend class Zone;

View File

@ -24,6 +24,7 @@
#include "pathing.h"
#include "position.h"
#include "aa_ability.h"
#include "aa.h"
#include <set>
#include <vector>
#include <memory>
@ -1327,6 +1328,7 @@ protected:
bool destructibleobject;
std::unordered_map<uint32, std::pair<uint32, uint32>> aa_ranks;
Timer aa_timers[aaTimerMax];
private:
void _StopSong(); //this is not what you think it is

View File

@ -31,7 +31,6 @@
#include "../common/linked_list.h"
#include "../common/servertalk.h"
#include "aa.h"
#include "client.h"
#include "entity.h"
#include "npc.h"

View File

@ -818,12 +818,8 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
}
if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast
AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id);
if(rank) {
CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED);
CastToClient()->SendAlternateAdvancementTimer(rank->spell_type, 0, 0x7fffffff);
CastToClient()->GetPTimers().Clear(&database, rank->spell_type + pTimerAAStart);
}
CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED);
CastToClient()->ResetAlternateAdvancementTimer(casting_spell_aa_id);
}
ZeroCastingVars(); // resets all the state keeping stuff