/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) 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 */ #include "../common/debug.h" #include using namespace std; #include #include #ifndef WIN32 #include #endif #include "faction.h" #include "zonedb.h" #include "masterentity.h" #include "zone.h" #include "../common/MiscFunctions.h" extern Zone* zone; #ifdef _WINDOWS #define snprintf _snprintf #endif //#define FACTIONS_DEBUG 5 const char *FactionValueToString(FACTION_VALUE fv) { switch(fv) { case FACTION_ALLY: return("Ally"); case FACTION_WARMLY: return("Warmly"); case FACTION_KINDLY: return("Kindly"); case FACTION_AMIABLE: return("Amiable"); case FACTION_INDIFFERENT: return("Indifferent"); case FACTION_APPREHENSIVE: return("Apprehensive"); case FACTION_DUBIOUS: return("Dubious"); case FACTION_THREATENLY: return("Threatenly"); case FACTION_SCOWLS: return("Scowls, ready to attack."); default: break; } return("Unknown Faction Con"); } //o-------------------------------------------------------------- //| Name: CalculateFaction; rembrant, Dec. 16, 2001 //o-------------------------------------------------------------- //| Notes: Returns the faction message value. //| Modify these values to taste. //o-------------------------------------------------------------- FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value) { #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, "called CalculateFaction(0x%x, %ld)", fm, (unsigned long)tmpCharacter_value); #endif int32 character_value = tmpCharacter_value; if (fm) character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod; if(character_value >= 1101) return FACTION_ALLY; if(character_value >= 701 && character_value <= 1100) return FACTION_WARMLY; if(character_value >= 401 && character_value <= 700) return FACTION_KINDLY; if(character_value >= 101 && character_value <= 400) return FACTION_AMIABLE; if(character_value >= 0 && character_value <= 100) return FACTION_INDIFFERENT; if(character_value >= -100 && character_value <= -1) return FACTION_APPREHENSIVE; if(character_value >= -700 && character_value <= -101) return FACTION_DUBIOUS; if(character_value >= -999 && character_value <= -701) return FACTION_THREATENLY; if(character_value <= -1000) return FACTION_SCOWLS; return FACTION_INDIFFERENT; } // neotokyo: this function should check if some races have more than one race define bool IsOfEqualRace(int r1, int r2) { if (r1 == r2) return true; // TODO: add more values switch(r1) { case DARK_ELF: if (r2 == 77) return true; break; case BARBARIAN: if (r2 == 90) return true; } return false; } // neotokyo: trolls endure ogres, dark elves, ... bool IsOfIndiffRace(int r1, int r2) { if (r1 == r2) return true; // TODO: add more values switch(r1) { case DARK_ELF: case OGRE: case TROLL: if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) return true; break; case HUMAN: case BARBARIAN: case HALF_ELF: case GNOME: case HALFLING: case WOOD_ELF: if (r2 == HUMAN || r2 == BARBARIAN || r2 == ERUDITE || r2 == HALF_ELF || r2 == GNOME || r2 == HALFLING || r2 == DWARF || r2 == HIGH_ELF || r2 == WOOD_ELF) return true; break; case ERUDITE: if (r2 == HUMAN || r2 == HALF_ELF) return true; break; case DWARF: if (r2 == HALFLING || r2 == GNOME) return true; break; case HIGH_ELF: if (r2 == WOOD_ELF) return true; break; case VAHSHIR: return true; case IKSAR: return false; } return false; } // returns what Other thinks of this FACTION_VALUE Client::GetReverseFactionCon(Mob* iOther) { #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, "called $s::GetReverseFactionCon(%s)", GetName(), iOther->GetName()); #endif if (GetOwnerID()) { return GetOwnerOrSelf()->GetReverseFactionCon(iOther); } iOther = iOther->GetOwnerOrSelf(); #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, " %s'd primary faction = %d", iOther->GetName(), iOther->GetPrimaryFaction()); #endif if (iOther->GetPrimaryFaction() < 0) return GetSpecialFactionCon(iOther); if (iOther->GetPrimaryFaction() == 0) return FACTION_INDIFFERENT; return GetFactionLevel(CharacterID(), 0, GetRace(), GetClass(), GetDeity(), iOther->GetPrimaryFaction(), iOther); } //this is called with 'this' as the mob being looked at, and //iOther the mob who is doing the looking. It should figure out //what iOther thinks about 'this' FACTION_VALUE NPC::GetReverseFactionCon(Mob* iOther) { #if FACTIONS_DEBUG >= 20 LogFile->write(EQEMuLog::Debug, "called N $s::GetReverseFactionCon(%s)", GetName(), iOther->GetName()); #endif _ZP(NPC_GetReverseFactionCon); iOther = iOther->GetOwnerOrSelf(); int primaryFaction= iOther->GetPrimaryFaction(); #if FACTIONS_DEBUG >= 20 LogFile->write(EQEMuLog::Debug, " %s'd primary faction = %d", iOther->GetName(), primaryFaction); #endif //I am pretty sure that this special faction call is backwards //and should be iOther->GetSpecialFactionCon(this) if (primaryFaction < 0) return GetSpecialFactionCon(iOther); if (primaryFaction == 0) return FACTION_INDIFFERENT; //if we are a pet, use our owner's faction stuff Mob *own = GetOwner(); if (own != NULL) return own->GetReverseFactionCon(iOther); //make sure iOther is an npc //also, if we dont have a faction, then they arnt gunna think anything of us either if(!iOther->IsNPC() || GetPrimaryFaction() == 0) return(FACTION_INDIFFERENT); //if we get here, iOther is an NPC too //otherwise, employ the npc faction stuff //so we need to look at iOther's faction table to see //what iOther thinks about our primary faction return(iOther->CastToNPC()->CheckNPCFactionAlly(GetPrimaryFaction())); } //Look through our faction list and return a faction con based //on the npc_value for the other person's primary faction in our list. FACTION_VALUE NPC::CheckNPCFactionAlly(int32 other_faction) { list::iterator cur,end; cur = faction_list.begin(); end = faction_list.end(); for(; cur != end; cur++) { struct NPCFaction* fac = *cur; if ((int32)fac->factionID == other_faction) { if (fac->npc_value > 0) return FACTION_ALLY; else if (fac->npc_value < 0) return FACTION_SCOWLS; else return FACTION_INDIFFERENT; } } return FACTION_INDIFFERENT; } bool NPC::IsFactionListAlly(uint32 other_faction) { /* list::iterator cur,end; cur = faction_list.begin(); end = faction_list.end(); for(; cur != end; cur++) { struct NPCFaction* fac = *cur; if (fac->factionID == other_faction && fac->npc_value > 0) return(true); } return(false);*/ return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); } // Faction Mods for Alliance type spells void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) { map :: const_iterator faction_bonus; typedef std::pair NewFactionBonus; faction_bonus = faction_bonuses.find(pFactionID); if(faction_bonus == faction_bonuses.end()) { faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); } else { if(faction_bonus->second :: const_iterator faction_bonus; typedef std::pair NewFactionBonus; faction_bonus = item_faction_bonuses.find(pFactionID); if(faction_bonus == item_faction_bonuses.end()) { item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); } else { if((bonus > 0 && faction_bonus->second < bonus) || (bonus < 0 && faction_bonus->second > bonus)) { item_faction_bonuses.erase(pFactionID); item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); } } } int32 Mob::GetFactionBonus(uint32 pFactionID) { map :: const_iterator faction_bonus; faction_bonus = faction_bonuses.find(pFactionID); if(faction_bonus != faction_bonuses.end()) { return (*faction_bonus).second; } return 0; } int32 Mob::GetItemFactionBonus(uint32 pFactionID) { map :: const_iterator faction_bonus; faction_bonus = item_faction_bonuses.find(pFactionID); if(faction_bonus != item_faction_bonuses.end()) { return (*faction_bonus).second; } return 0; } void Mob::ClearItemFactionBonuses() { map :: iterator itr; for(itr = item_faction_bonuses.begin(); itr != item_faction_bonuses.end(); itr++) { item_faction_bonuses.erase(itr->first); } } FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, "called $s::GetSpecialFactionCon(%s)", GetName(), iOther->GetName()); #endif if (!iOther) return FACTION_INDIFFERENT; iOther = iOther->GetOwnerOrSelf(); Mob* self = this->GetOwnerOrSelf(); bool selfAIcontrolled = self->IsAIControlled(); bool iOtherAIControlled = iOther->IsAIControlled(); int selfPrimaryFaction = self->GetPrimaryFaction(); int iOtherPrimaryFaction = iOther->GetPrimaryFaction(); #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, " GSFC %d %d %d %d", selfAIcontrolled, iOtherAIControlled, selfPrimaryFaction, iOtherPrimaryFaction); #endif if (selfPrimaryFaction >= 0 && selfAIcontrolled) return FACTION_INDIFFERENT; if (iOther->GetPrimaryFaction() >= 0) return FACTION_INDIFFERENT; /* special values: -2 = indiff to player, ally to AI on special values, indiff to AI -3 = dub to player, ally to AI on special values, indiff to AI -4 = atk to player, ally to AI on special values, indiff to AI -5 = indiff to player, indiff to AI -6 = dub to player, indiff to AI -7 = atk to player, indiff to AI -8 = indiff to players, ally to AI on same value, indiff to AI -9 = dub to players, ally to AI on same value, indiff to AI -10 = atk to players, ally to AI on same value, indiff to AI -11 = indiff to players, ally to AI on same value, atk to AI -12 = dub to players, ally to AI on same value, atk to AI -13 = atk to players, ally to AI on same value, atk to AI */ switch (iOtherPrimaryFaction) { case -2: // -2 = indiff to player, ally to AI on special values, indiff to AI if (selfAIcontrolled && iOtherAIControlled) return FACTION_ALLY; else return FACTION_INDIFFERENT; case -3: // -3 = dub to player, ally to AI on special values, indiff to AI if (selfAIcontrolled && iOtherAIControlled) return FACTION_ALLY; else return FACTION_DUBIOUS; case -4: // -4 = atk to player, ally to AI on special values, indiff to AI if (selfAIcontrolled && iOtherAIControlled) return FACTION_ALLY; else return FACTION_SCOWLS; case -5: // -5 = indiff to player, indiff to AI return FACTION_INDIFFERENT; case -6: // -6 = dub to player, indiff to AI if (selfAIcontrolled && iOtherAIControlled) return FACTION_INDIFFERENT; else return FACTION_DUBIOUS; case -7: // -7 = atk to player, indiff to AI if (selfAIcontrolled && iOtherAIControlled) return FACTION_INDIFFERENT; else return FACTION_SCOWLS; case -8: // -8 = indiff to players, ally to AI on same value, indiff to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_INDIFFERENT; } else return FACTION_INDIFFERENT; case -9: // -9 = dub to players, ally to AI on same value, indiff to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_INDIFFERENT; } else return FACTION_DUBIOUS; case -10: // -10 = atk to players, ally to AI on same value, indiff to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_INDIFFERENT; } else return FACTION_SCOWLS; case -11: // -11 = indiff to players, ally to AI on same value, atk to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_SCOWLS; } else return FACTION_INDIFFERENT; case -12: // -12 = dub to players, ally to AI on same value, atk to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_SCOWLS; } else return FACTION_DUBIOUS; case -13: // -13 = atk to players, ally to AI on same value, atk to AI if (selfAIcontrolled && iOtherAIControlled) { if (selfPrimaryFaction == iOtherPrimaryFaction) return FACTION_ALLY; else return FACTION_SCOWLS; } else return FACTION_SCOWLS; default: return FACTION_INDIFFERENT; } } //o-------------------------------------------------------------- //| Name: GetFactionLevel; rembrant, Dec. 16, 2001 //o-------------------------------------------------------------- //| Notes: Gets the characters faction standing with the //| specified NPC. //| Will return Indifferent on failure. //o-------------------------------------------------------------- FACTION_VALUE Client::GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc) { #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, "called %s::GetFactionLevel(%lu, %lu, %lu, %lu, %lu, %lu, %s)", GetName(), (unsigned long)char_id, (unsigned long)npc_id, (unsigned long)p_race, (unsigned long)p_class, (unsigned long)p_deity, (unsigned long)pFaction, tnpc?tnpc->GetName():"(NULL)"); #endif _ZP(Client_GetFactionLevel); if (pFaction < 0) return GetSpecialFactionCon(tnpc); FACTION_VALUE fac = FACTION_INDIFFERENT; //int32 pFacValue; -Trumpcard: commenting. Not currently used. int32 tmpFactionValue; FactionMods fmods; // neotokyo: few optimizations if (GetFeigned()) return FACTION_INDIFFERENT; if (invisible_undead && tnpc && !tnpc->SeeInvisibleUndead()) return FACTION_INDIFFERENT; if (IsInvisible(tnpc)) return FACTION_INDIFFERENT; if (tnpc && tnpc->GetOwnerID() != 0) // pets con amiably to owner and indiff to rest if (char_id == tnpc->GetOwner()->CastToClient()->CharacterID()) return FACTION_AMIABLE; else return FACTION_INDIFFERENT; //First get the NPC's Primary faction if(pFaction > 0) { //Get the faction data from the database if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction)) { //Get the players current faction with pFaction tmpFactionValue = GetCharacterFactionLevel(pFaction); // Everhood - tack on any bonuses from Alliance type spell effects tmpFactionValue += GetFactionBonus(pFaction); tmpFactionValue += GetItemFactionBonus(pFaction); //Return the faction to the client fac = CalculateFaction(&fmods, tmpFactionValue); //Message(0,"Faction: %i %i %i %i",fmods.base,fmods.class_mod,fmods.race_mod,fmods.deity_mod); //Message(0,"tmpFactionValue: %i, fac: %i",tmpFactionValue,fac); } } else { //pFaction == 0 return(FACTION_INDIFFERENT); /* I think this is a good idea, but the consensus seems to be that if the faction is not in the DB, it should not be made up based on race and class like this is doing. fmods.base = 0; fmods.deity_mod = 0; if (tnpc && p_class == (uint32) tnpc->GetClass()%16) fmods.class_mod = 301; else if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType == 0) fmods.class_mod = -101; else fmods.class_mod = 0; if (tnpc && IsOfEqualRace(p_race, tnpc->GetRace()) ) fmods.race_mod = 101; else if (tnpc && IsOfIndiffRace(p_race, tnpc->GetRace()) ) fmods.race_mod = 0; else if (tnpc) fmods.race_mod = -51; else fmods.race_mod = 0; fac = CalculateFaction(&fmods, 0); */ } // merchant fix if (tnpc && tnpc->IsNPC() && tnpc->CastToNPC()->MerchantType && (fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) fac = FACTION_DUBIOUS; if (tnpc != 0 && fac != FACTION_SCOWLS && tnpc->CastToNPC()->CheckAggro(this)) fac = FACTION_THREATENLY; #if FACTIONS_DEBUG >= 5 LogFile->write(EQEMuLog::Debug, "%s::GetFactionLevel() result: %d", GetName(), fac); #endif return fac; } //o-------------------------------------------------------------- //| Name: SetFactionLevel; rembrant, Dec. 20, 2001 //o-------------------------------------------------------------- //| Notes: Sets the characters faction standing with the //| specified NPC. //o-------------------------------------------------------------- void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity) { _ZP(Client_SetFactionLevel); int32 faction_id[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; int32 npc_value[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; uint8 temp[MAX_NPC_FACTIONS]={ 0,0,0,0,0,0,0,0,0,0 }; int32 mod; int32 t; int32 tmpValue; int32 current_value; FactionMods fm; // Get the npc faction list if(!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp)) return; for(int i = 0;iitembonuses.HeroicCHA) { int faction_mod = itembonuses.HeroicCHA / 5; // If our result isn't truncated, then just do that if(npc_value[i] * faction_mod / 100 != 0) npc_value[i] += npc_value[i] * faction_mod / 100; // If our result is truncated, then double a mob's value every once and a while to equal what they would have got else { if(MakeRandomInt(0, 100) < faction_mod) npc_value[i] *= 2; } } //figure out their modifier mod = fm.base + fm.class_mod + fm.race_mod + fm.deity_mod; if(mod > MAX_FACTION) mod = MAX_FACTION; else if(mod < MIN_FACTION) mod = MIN_FACTION; // Calculate the faction if(npc_value[i] != 0) { tmpValue = current_value + mod + npc_value[i]; // Make sure faction hits don't go to GMs... if (m_pp.gm==1 && (tmpValue < current_value)) { tmpValue = current_value; } // Make sure we dont go over the min/max faction limits if(tmpValue >= MAX_FACTION) { t = MAX_FACTION - mod; if(current_value == t) { //do nothing, it is already maxed out } else if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], t, temp[i], factionvalues))) { return; } } else if(tmpValue <= MIN_FACTION) { t = MIN_FACTION - mod; if(current_value == t) { //do nothing, it is already maxed out } else if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], t, temp[i], factionvalues))) { return; } } else { if(!(database.SetCharacterFactionLevel(char_id, faction_id[i], current_value + npc_value[i], temp[i], factionvalues))) { return; } } if(tmpValue <= MIN_FACTION) tmpValue = MIN_FACTION; char* msg = BuildFactionMessage(npc_value[i],faction_id[i],tmpValue,temp[i]); if (msg != 0) Message(0, msg); safe_delete_array(msg); } } } return; } void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp) { _ZP(Client_SetFactionLevel2); // int32 tmpValue; int32 current_value; // FactionMods fm; //Get the npc faction list if(faction_id > 0 && value != 0) { //Get the faction modifiers current_value = GetCharacterFactionLevel(faction_id) + value; if(!(database.SetCharacterFactionLevel(char_id, faction_id, current_value, temp, factionvalues))) return; char* msg = BuildFactionMessage(value, faction_id, current_value, temp); if (msg != 0) Message(0, msg); safe_delete(msg); } return; } int32 Client::GetCharacterFactionLevel(int32 faction_id) { if (faction_id <= 0) return 0; faction_map::iterator res; res = factionvalues.find(faction_id); if(res == factionvalues.end()) return(0); return(res->second); } // returns the character's faction level, adjusted for racial, class, and deity modifiers int32 Client::GetModCharacterFactionLevel(int32 faction_id) { int32 Modded = GetCharacterFactionLevel(faction_id); FactionMods fm; if(database.GetFactionData(&fm,GetClass(),GetRace(),GetDeity(),faction_id)) Modded += fm.base + fm.class_mod + fm.race_mod + fm.deity_mod; if (Modded > MAX_FACTION) Modded = MAX_FACTION; return Modded; } bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race_mod, uint32 deity_mod, int32 faction_id) { if (faction_id <= 0 || faction_id > (int32) max_faction) return false; if (faction_array[faction_id] == 0){ return false; } fm->base = faction_array[faction_id]->base; if(class_mod > 0) { char str[32]; sprintf(str, "c%u", class_mod); std::map::const_iterator iter = faction_array[faction_id]->mods.find(str); if(iter != faction_array[faction_id]->mods.end()) { fm->class_mod = iter->second; } else { fm->class_mod = 0; } } else { fm->class_mod = 0; } if(race_mod > 0) { char str[32]; sprintf(str, "r%u", race_mod); std::map::iterator iter = faction_array[faction_id]->mods.find(str); if(iter != faction_array[faction_id]->mods.end()) { fm->race_mod = iter->second; } else { fm->race_mod = 0; } } else { fm->race_mod = 0; } if(deity_mod > 0) { char str[32]; sprintf(str, "d%u", deity_mod); std::map::iterator iter = faction_array[faction_id]->mods.find(str); if(iter != faction_array[faction_id]->mods.end()) { fm->deity_mod = iter->second; } else { fm->deity_mod = 0; } } else { fm->deity_mod = 0; } return true; } bool ZoneDatabase::LoadFactionValues(uint32 char_id, faction_map & val_list) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; MYSQL_RES *result; if (RunQuery(query, MakeAnyLenString(&query, "SELECT faction_id,current_value FROM faction_values WHERE char_id = %i",char_id), errbuf, &result)) { safe_delete_array(query); bool ret = LoadFactionValues_result(result, val_list); mysql_free_result(result); return ret; } else { cerr << "Error in LoadFactionValues query '" << query << "' " << errbuf << endl; safe_delete_array(query); } return false; } bool ZoneDatabase::LoadFactionValues_result(MYSQL_RES* result, faction_map & val_list) { MYSQL_ROW row; while((row = mysql_fetch_row(result))) { val_list[atoi(row[0])] = atoi(row[1]); } return true; } //o-------------------------------------------------------------- //| Name: BuildFactionMessage; rembrant, Dec. 16, 2001 //o-------------------------------------------------------------- //| Purpose: duh? //o-------------------------------------------------------------- char* BuildFactionMessage(int32 tmpvalue, int32 faction_id, int32 totalvalue, uint8 temp) { /* This should be replaced to send string-ID based messages using: #define FACTION_WORST 469 //Your faction standing with %1 could not possibly get any worse. #define FACTION_WORSE 470 //Your faction standing with %1 got worse. #define FACTION_BEST 471 //Your faction standing with %1 could not possibly get any better. #define FACTION_BETTER 472 //Your faction standing with %1 got better. some day. */ //tmpvalue is the change as best I can tell. char *faction_message = 0; char name[50]; if(database.GetFactionName(faction_id, name, sizeof(name)) == false) { snprintf(name, sizeof(name),"Faction%i",faction_id); } if(tmpvalue == 0 || temp == 1 || temp == 2) { return 0; } else if (totalvalue >= MAX_FACTION) { MakeAnyLenString(&faction_message, "Your faction standing with %s could not possibly get any better!", name); return faction_message; } else if(tmpvalue > 0 && totalvalue < MAX_FACTION) { MakeAnyLenString(&faction_message, "Your faction standing with %s has gotten better!", name); return faction_message; } else if(tmpvalue < 0 && totalvalue > MIN_FACTION) { MakeAnyLenString(&faction_message, "Your faction standing with %s has gotten worse!", name); return faction_message; } else if(totalvalue <= MIN_FACTION) { MakeAnyLenString(&faction_message, "Your faction standing with %s could not possibly get any worse!", name); return faction_message; } return 0; } //o-------------------------------------------------------------- //| Name: GetFactionName; rembrant, Dec. 16 //o-------------------------------------------------------------- //| Notes: Retrieves the name of the specified faction //| Returns false on failure. //o-------------------------------------------------------------- bool ZoneDatabase::GetFactionName(int32 faction_id, char* name, uint32 buflen) { if ((faction_id <= 0) || faction_id > int32(max_faction) ||(faction_array[faction_id] == 0)) return false; if (faction_array[faction_id]->name[0] != 0) { strn0cpy(name, faction_array[faction_id]->name, buflen); return true; } return false; } //o-------------------------------------------------------------- //| Name: GetNPCFactionList; rembrant, Dec. 16, 2001 //o-------------------------------------------------------------- //| Purpose: Gets a list of faction_id's and values bound to //| the npc_id. //| Returns false on failure. //o-------------------------------------------------------------- bool ZoneDatabase::GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, int32* value, uint8* temp, int32* primary_faction) { if (npcfaction_id <= 0) { if (primary_faction) *primary_faction = npcfaction_id; return true; } const NPCFactionList* nfl = GetNPCFactionEntry(npcfaction_id); if (!nfl) return false; if (primary_faction) *primary_faction = nfl->primaryfaction; for (int i=0; ifactionid[i]; value[i] = nfl->factionvalue[i]; temp[i] = nfl->factiontemp[i]; } return true; } //o-------------------------------------------------------------- //| Name: SetCharacterFactionLevel; rembrant, Dec. 20, 2001 //o-------------------------------------------------------------- //| Purpose: Update characters faction level with specified //| faction_id to specified value. //| Returns false on failure. //o-------------------------------------------------------------- bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list) { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; uint32 affected_rows = 0; if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM faction_values WHERE char_id=%i AND faction_id = %i", char_id, faction_id), errbuf)) { cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << errbuf << endl; safe_delete_array(query); return false; } if(value == 0) { safe_delete_array(query); return true; } if(temp == 2) temp = 0; if(temp == 3) temp = 1; if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO faction_values (char_id,faction_id,current_value,temp) VALUES (%i,%i,%i,%i)", char_id, faction_id,value,temp), errbuf, 0, &affected_rows)) { cerr << "Error in SetCharacterFactionLevel query '" << query << "' " << errbuf << endl; safe_delete_array(query); return false; } safe_delete_array(query); if (affected_rows == 0) { return false; } val_list[faction_id] = value; return(true); } bool ZoneDatabase::LoadFactionData() { char errbuf[MYSQL_ERRMSG_SIZE]; char *query = 0; MYSQL_RES *result; MYSQL_ROW row; query = new char[256]; strcpy(query, "SELECT MAX(id) FROM faction_list"); if (RunQuery(query, strlen(query), errbuf, &result)) { safe_delete_array(query); row = mysql_fetch_row(result); if (row && row[0]) { max_faction = atoi(row[0]); faction_array = new Faction*[max_faction+1]; for(unsigned int i=0; iname, row[1], 50); faction_array[index]->base = atoi(row[2]); char sec_errbuf[MYSQL_ERRMSG_SIZE]; MYSQL_RES *sec_result; MYSQL_ROW sec_row; MakeAnyLenString(&query, "SELECT `mod`, `mod_name` FROM `faction_list_mod` WHERE faction_id=%u", index); if (RunQuery(query, strlen(query), sec_errbuf, &sec_result)) { while((sec_row = mysql_fetch_row(sec_result))) { faction_array[index]->mods[sec_row[1]] = atoi(sec_row[0]); } mysql_free_result(sec_result); } safe_delete_array(query); } mysql_free_result(result); } else { cerr << "Error in LoadFactionData '" << query << "' " << errbuf << endl; safe_delete_array(query); return false; } } else { mysql_free_result(result); } } else { cerr << "Error in LoadFactionData '" << query << "' " << errbuf << endl; safe_delete_array(query); return false; } return true; } bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, list *faction_list, int32* primary_faction) { if (nfl_id <= 0) { list::iterator cur,end; cur = faction_list->begin(); end = faction_list->end(); for(; cur != end; cur++) { struct NPCFaction* tmp = *cur; safe_delete(tmp); } faction_list->clear(); if (primary_faction) *primary_faction = nfl_id; return true; } const NPCFactionList* nfl = GetNPCFactionEntry(nfl_id); if (!nfl) return false; if (primary_faction) *primary_faction = nfl->primaryfaction; list::iterator cur,end; cur = faction_list->begin(); end = faction_list->end(); for(; cur != end; cur++) { struct NPCFaction* tmp = *cur; safe_delete(tmp); } faction_list->clear(); for (int i=0; ifactionid[i]) { pFac = new struct NPCFaction; pFac->factionID = nfl->factionid[i]; pFac->value_mod = nfl->factionvalue[i]; pFac->npc_value = nfl->factionnpcvalue[i]; pFac->temp = nfl->factiontemp[i]; /* if (nfl->primaryfaction == pFac->factionID) pFac->primary = true; else pFac->primary = false; */ faction_list->push_back(pFac); } } return true; } bool Client::HatedByClass(uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction) { bool Result = false; _ZP(Client_GetFactionLevel); int32 tmpFactionValue; FactionMods fmods; //First get the NPC's Primary faction if(pFaction > 0) { //Get the faction data from the database if(database.GetFactionData(&fmods, p_class, p_race, p_deity, pFaction)) { tmpFactionValue = GetCharacterFactionLevel(pFaction); tmpFactionValue += GetFactionBonus(pFaction); tmpFactionValue += GetItemFactionBonus(pFaction); CalculateFaction(&fmods, tmpFactionValue); if(fmods.class_mod < fmods.race_mod) Result = true; } } return Result; }