eqemu-server/zone/oldcode.cpp
2013-02-16 16:14:39 -08:00

1860 lines
44 KiB
C++

/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 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 <iostream>
using namespace std;
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#ifdef _CRTDBG_MAP_ALLOC
#undef new
#endif
#include <fstream>
#ifdef _CRTDBG_MAP_ALLOC
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
using namespace std;
#ifdef WIN32
#include <conio.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
bool spells_loaded = false;
volatile bool RunLoops = true;
extern volatile bool ZoneLoaded;
#ifdef SHAREMEM
#include "../common/EMuShareMem.h"
extern LoadEMuShareMemDLL EMuShareMemDLL;
#ifndef WIN32
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#ifndef FREEBSD
union semun {
int val;
struct semid_ds *buf;
ushort *array;
struct seminfo *__buf;
void *__pad;
};
#endif
#endif
#endif
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/EQStream.h"
#include "../common/eq_packet_structs.h"
#include "../common/Mutex.h"
#include "../common/version.h"
#include "../common/files.h"
#include "../common/EQEMuError.h"
#include "../common/packet_dump_file.h"
#include "masterentity.h"
#include "worldserver.h"
#include "net.h"
#include "spdat.h"
#include "zone.h"
#include "command.h"
#include "parser.h"
#include "embparser.h"
#ifndef NEW_LoadSPDat
void LoadSPDat(SPDat_Spell_Struct** SpellsPointer) {
//FILE *fp;
//cout << "Beginning Spells memset." << endl;
int u;
//for (u = 0; u < SPDAT_RECORDS; u++)
//{ //cout << u << ' ';
memset((char*) &spells,0,sizeof(SPDat_Spell_Struct)*SPDAT_RECORDS);
//}
//cout << "Memset finished\n";
char temp=' ';
int tempid=0;
char token[64]="";
int a = 0;
char sep='^';
LogFile->write(EQEMuLog::Normal, "If this is the last message you see, you forgot to move spells_en.txt from your EQ dir to this dir.");
#ifdef FREEBSD
#error ifstreams seem to break BSD...
#endif
ifstream in;in.open(SPELLS_FILE);
if(!in.is_open()){
LogFile->write(EQEMuLog::Error, "File '%s' not found in same directory as zone.exe, spell loading FAILED!", SPELLS_FILE);
return;
}
//while(!in.eof())
//{in >> temp;}
//for(int x =0; x< spellsen_size; x++)
// memset((char*) &spells[x],0,sizeof(SPDat_Spell_Struct));
while(tempid <= SPDAT_RECORDS-1)
{
//if(tempid>3490)
//{
// cout << "BLEH";
// getch();
//}
//in.getline(&temp, 624);
in.get(temp);
while(chrcmpI(&temp, &sep))
{
strncat(token,&temp,1);
a++;//cout << temp<< ' ';
in.get(temp);
}
tempid=atoi(token);
if(tempid>=SPDAT_RECORDS)
break;
//cout << "TempID: " << tempid << endl;
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].name,token,a);
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
//cout << spells[tempid].name << '^';
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].player_1,token,a);
//cout << spells[tempid].player_1 << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].teleport_zone,token,a);
//cout << spells[tempid].teleport_zone << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].you_cast,token,a);
//cout << spells[tempid].you_cast << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].other_casts,token,a);
//cout << spells[tempid].other_casts << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].cast_on_you,token,a);
//cout << spells[tempid].cast_on_you << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].cast_on_other,token,a);
//cout << spells[tempid].cast_on_other << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
strncpy(spells[tempid].spell_fades,token,a);
//cout << spells[tempid].spell_fades << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
in.get(temp);
}
spells[tempid].range=atof(token);
//cout << spells[tempid].range << '^';
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].aoerange=atof(token);
//cout << spells[tempid].aoerange << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].pushback=atof(token);
//cout << spells[tempid].pushback << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].pushup=atof(token);
//cout << spells[tempid].pushup << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].cast_time=atoi(token);
//cout << spells[tempid].cast_time << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].recovery_time=atoi(token);
//cout << spells[tempid].recovery_time << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].recast_time=atoi(token);
//cout << spells[tempid].recast_time << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].buffdurationformula=atoi(token);
//cout << spells[tempid].buffdurationformula << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].buffduration=atoi(token);
//cout << spells[tempid].buffduration << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].ImpactDuration=atoi(token);
//cout << spells[tempid].ImpactDuration<< '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].mana=atoi(token);
//cout << spells[tempid].mana << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
int y;
for(y=0; y< 12;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].base[y]=atoi(token);
//cout << spells[tempid].base[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
for(y=0; y< 12;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].max[y]=atoi(token);
//cout << spells[tempid].max[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].icon=atoi(token);
//cout << spells[tempid].icon << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].memicon=atoi(token);
//cout << spells[tempid].memicon << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
for(y=0; y< 4;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].components[y]=atoi(token);
//cout << spells[tempid].components[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
for(y=0; y< 4;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].component_counts[y]=atoi(token);//atoi(token);
//cout << spells[tempid].component_counts[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
for(y=0; y< 4;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].NoexpendReagent[y]=atoi(token); //NoExpend Reagent
//cout << spells[tempid].NoexpendReagent[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
for(y=0; y< 12;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].formula[y]=atoi(token);
//cout << spells[tempid].formula[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].LightType=atoi(token);
//cout << spells[tempid].LightType << '^';
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].goodEffect=atoi(token);
//cout << spells[tempid].goodEffect << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].Activated=atoi(token);
//cout << spells[tempid].Activated << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].resisttype=atoi(token);
//cout << spells[tempid].resisttype << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
for(y=0; y< 12;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].effectid[y]=atoi(token);
//cout << spells[tempid].effectid[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].targettype=atoi(token);
//cout << spells[tempid].targettype << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].basediff=atoi(token);
//cout << spells[tempid].basediff<< '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].skill=atoi(token);
//cout << spells[tempid].skill << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].zonetype=atoi(token);
//cout << spells[tempid].zonetype << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].EnvironmentType=atoi(token);
//cout << spells[tempid].EnvironmentType << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].TimeOfDay=atoi(token);
//cout << spells[tempid].TimeOfDay << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
for(y=0; y< 15;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].classes[y]= atoi(token);
//cout << spells[tempid].classes[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
} //cout << "end class";
/*for(y=0; y< 3;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].unknown1[y]=atoi(token);
cout << spells[tempid].unknown1[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].unknown2=atoi(token);
cout << spells[tempid].unknown2 << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
*/
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].CastingAnim=atoi(token);
//cout << spells[tempid].CastingAnim << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].TargetAnim=atoi(token);
//cout << spells[tempid].TargetAnim << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].TravelType=atoi(token);
//cout << spells[tempid].TravelType << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].SpellAffectIndex=atoi(token);
//cout << spells[tempid].SpellAffectIndex << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
for(y=0; y< 23;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].Spacing2[y]=atoi(token);
//cout << spells[tempid].base[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].ResistDiff=atoi(token);
//cout << spells[tempid].ResistDiff << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
in.get(temp);
for(y=0; y< 2;y++)
{
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].Spacing3[y]=atoi(token);
//cout << spells[tempid].base[y] << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
}
in.get(temp);
while(chrcmpI(&temp,&sep))
{
strncat(token,&temp,1);
a++;
in.get(temp);
}
spells[tempid].RecourseLink = atoi(token);
//cout << spells[tempid].RecourseLink << '^';
a=0;
for(u=0;u<64;u++)
token[u]=(char)0;
while(temp!='\n')
in.get(temp);
//cout << endl;
if(tempid==SPDAT_RECORDS-1) break;
}
//for(u=0;u< SPDAT_RECORDS;u++)
// cout << u << ' ' << spells[u].name << '^';
spells_loaded = true;
cout << "Spells loaded.\n";
in.close();
}
#endif
/*void EntityList::SendAATimer(uint32 charid,UseAA_Struct* uaa){
Client* client2=this->GetClientByCharID(charid);
if(!client2){
LogFile->write(EQEMuLog::Error, "Error in SendAATimer: Couldnt find character!");
return;
}
client2->SendAATimer(uaa);
}
void ZoneDatabase::UpdateAndDeleteAATimers(uint32 charid){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
char *query2 = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "delete from aa_timers where charid=%i and UNIX_TIMESTAMP(now())>=end",charid), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query, errbuf);
}
if (!RunQuery(query2, MakeAnyLenString(&query2, "update aa_timers set end=end-(UNIX_TIMESTAMP(now())-begin),begin=UNIX_TIMESTAMP(now()) where charid=%i",charid), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query2, errbuf);
}
safe_delete_array(query);
safe_delete_array(query2);
}
void ZoneDatabase::UpdateTimersClientConnected(uint32 charid){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if (!RunQuery(query, MakeAnyLenString(&query, "update aa_timers set end=(UNIX_TIMESTAMP(now())+(end-begin)),begin=UNIX_TIMESTAMP(now()) where charid=%i",charid), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query, errbuf);
}
safe_delete_array(query);
}
void ZoneDatabase::GetAATimers(uint32 charid){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT ability,begin,end from aa_timers WHERE charid=%i", charid), errbuf, &result)) {
while( ( row = mysql_fetch_row(result) ) ){
UseAA_Struct* uaa=new UseAA_Struct();
uaa->ability=atoi(row[0]);
uaa->begin=atoi(row[1]);
uaa->end=atoi(row[2]);
entity_list.SendAATimer(charid,uaa);
safe_delete(uaa);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Database::GetAATimers query '%s' %s", query, errbuf);
}
safe_delete_array(query);
}
uint32 ZoneDatabase::GetTimerRemaining(uint32 charid,uint32 ability){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
uint32 remain=0;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT end-begin from aa_timers WHERE charid=%i and ability=%i", charid,ability), errbuf, &result)) {
if((row=mysql_fetch_row(result))){
remain=atoi(row[0]);
}
mysql_free_result(result);
}
else {
LogFile->write(EQEMuLog::Error, "Database::GetTimerRemaining query '%s' %s", query, errbuf);
}
safe_delete_array(query);
return remain;
}
void ZoneDatabase::UpdateAATimers(uint32 charid,uint32 endtime,uint32 begintime,uint32 ability){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
if(begintime==0){
if (!RunQuery(query, MakeAnyLenString(&query, "replace into aa_timers (charid,end,begin,ability) values(%i,UNIX_TIMESTAMP(now())+%i,UNIX_TIMESTAMP(now()),%i)",charid,endtime,ability), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query, errbuf);
}
}
else{
if (!RunQuery(query, MakeAnyLenString(&query, "replace into aa_timers (charid,end,begin,ability) values(%i,%i,%i,%i)",charid,endtime,begintime,ability), errbuf)) {
LogFile->write(EQEMuLog::Error, "UpdateAATimers query '%s' %s", query, errbuf);
}
}
safe_delete_array(query);
}*/
/*
uint16 Client::GetCombinedAC_TEST() {
int ac1;
ac1 = GetRawItemAC();
if (m_pp.class_ != WIZARD && m_pp.class_ != MAGICIAN && m_pp.class_ != NECROMANCER && m_pp.class_ != ENCHANTER) {
ac1 = ac1*4/3;
}
ac1 += GetSkill(DEFENSE)/3;
if (GetAGI() > 70) {
ac1 += GetAGI()/20;
}
int ac2;
ac2 = GetRawItemAC();
if (m_pp.class_ != WIZARD && m_pp.class_ != MAGICIAN && m_pp.class_ != NECROMANCER && m_pp.class_ != ENCHANTER) {
ac2 = ac2*4/3;
}
ac2 += GetSkill(DEFENSE)*400/255;
int combined_ac = (ac1+ac2)*1000/847;
return combined_ac;
float combined_ac = ((float)ac1+(float)ac2)*1000.0f/847.0f;
return (uint16) combined_ac;//*10.0f)-10;
}
*/
/*bool Client::GetIncreaseSpellDurationItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsIncreaseDurationSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
bool Client::GetReduceManaCostItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsReduceManaSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
bool Client::GetReduceCastTimeItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsReduceCastTimeSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
bool Client::GetExtendedRangeItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsExtRangeSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
bool Client::GetImprovedHealingItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsImprovedHealingSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
bool Client::GetImprovedDamageItem(uint16 &spell_id, char *itemname)
{
for (int i=0; i<22; i++) {
const ItemInst* inst = m_inv[i];
if (!inst || !inst->IsType(ItemTypeCommon))
continue;
const Item_Struct* item = inst->GetItem();
if (item->FocusId && (item->FocusId != 0xFFFF)) {
if (IsImprovedDamageSpell(item->FocusId)) {
spell_id = item->FocusId;
if (itemname)
strcpy(itemname, item->Name);
return true;
}
}
}
return false;
}
int32 Client::GenericFocus(uint16 spell_id, uint16 modspellid)
{
int modifier = 100, i;
const SPDat_Spell_Struct &spell = spells[spell_id];
const SPDat_Spell_Struct &modspell = spells[modspellid];
for (i = 0; i < EFFECT_COUNT; i++)
{
if(IsBlankSpellEffect(modspellid, i))
continue;
switch( spells[modspellid].effectid[i] )
{
case SE_LimitMaxLevel:
if (spell.classes[(GetClass()%16) - 1] > modspell.base[i])
return 100;
break;
case SE_LimitMinLevel:
if (spell.classes[(GetClass()%16) - 1] < modspell.base[i])
return 100;
break;
case SE_IncreaseRange:
modifier += modspell.base[i];
break;
case SE_IncreaseSpellHaste:
modifier -= modspell.base[i];
break;
case SE_IncreaseSpellDuration:
modifier += modspell.base[i];
break;
case SE_LimitSpell:
// negative sign means exclude
// positive sign means include
if (modspell.base[i] < 0)
{
if (modspell.base[i] * (-1) == spell_id)
return 100;
}
else
{
if (spells[modspellid].base[i] != spell_id)
return 100;
}
break;
case SE_LimitEffect:
switch( spells[modspellid].base[i] )
{
case -147:
if (IsPercentalHealSpell(spell_id))
return 100;
break;
case -101:
if (IsCHDurationSpell(spell_id))
return 100;
break;
case -40:
if (IsInvulnerabilitySpell(spell_id))
return 100;
break;
case -32:
if (IsSummonItemSpell(spell_id))
return 100;
break;
case 0:
if (!IsEffectHitpointsSpell(spell_id))
return 100;
break;
case 33:
if (!IsSummonPetSpell(spell_id))
return 100;
break;
case 36:
if (!IsPoisonCounterSpell(spell_id))
return 100;
break;
case 71:
if (!IsSummonSkeletonSpell(spell_id))
return 100;
break;
default:
LogFile->write(EQEMuLog::Normal, "GenericFocus: unknown limit effect %d", spells[modspellid].base[i]);
}
break;
case SE_LimitCastTime:
if (modspell.base[i] > (int16)spell.cast_time)
return 100;
break;
case SE_LimitSpellType:
switch( spells[modspellid].base[i] )
{
case 0:
if (!IsDetrimentalSpell(spell_id))
return 100;
break;
case 1:
if (!IsBeneficialSpell(spell_id))
return 100;
break;
default:
LogFile->write(EQEMuLog::Normal, "GenericFocus: unknown limit spelltype %d", spells[modspellid].base[i]);
}
break;
case SE_LimitMinDur:
if (modspell.base[i] > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration))
return 100;
break;
case SE_ImprovedDamage:
case SE_ImprovedHeal:
modifier += modspell.base[i];
break;
case SE_ReduceManaCost:
modifier -= modspell.base[i];
break;
default:
LogFile->write(EQEMuLog::Normal, "GenericFocus: unknown effectid %d", modspell.effectid[i]);
}
}
return modifier;
}
*/
/*void Client::Discipline(ClientDiscipline_Struct* disc_in, Mob* tar) {
Message(0, "Disc packet id=%d, %x,%x,%x", disc_in->disc_id, disc_in->unknown3[0], disc_in->unknown3[1], disc_in->unknown3[2]);
if (!p_timers.Expired(&database, pTimerDisciplineReuse)) {
char val1[20]={0};
char val2[20]={0};
uint32 remain = p_timers.GetRemainingTime(pTimerDisciplineReuse);
Message_StringID(0,DISCIPLINE_CANUSEIN,ConvertArray((remain)/60,val1),ConvertArray(remain%60,val2));
//Message(0,"You can use a new discipline in %i minutes %i seconds.", (disc_timer.GetRemainingTime()/1000)/60, disc_timer.GetRemainingTime()/1000%60);
return;
}
//reuse times are a little messes up, they should scale down somehow
//as you gain in levels, but im not sure how, so its just a lvl 60 bonus right now
//should change this to check classes better.
//both in seconds, converted at the end.
uint32 duration = 0;
uint32 reuse = 0;
switch(disc_in->disc_id){
// Shared?
case discResistant: { // Resistant
// 1 minute duration
// 1 hour reuse
// +3 to +10 to resists
if (GetLevel()<=29)
return;
duration = 60;
reuse = 60*60;
entity_list.MessageClose(this, false, 100, 0, "%s has become more resistant!", GetName());
break;
}
case discFearless: { // Fearless
// 11 second duration
// 1 hour reuse
// 100% fear immunity
if (GetLevel()<=39)
return;
duration = 11;
reuse = 60*60;
entity_list.MessageClose_StringID(this, false, 100, 0, DISCIPLINE_FEARLESS, GetName());
//entity_list.MessageClose(this, false, 100, 0, "%s becomes fearless!", GetName());
break;
}
case discWhirlwind: { // Counterattack/Whirlwind/Furious
// warrior level 56
// rogue/monk level 53
// 9 second duration
// 1 hour reuse
if ( (GetClass() == WARRIOR && GetLevel() <= 56)
||(GetLevel() <= 53)
) return;
duration = 9;
reuse = 60*60;
entity_list.MessageClose(this, false, 100, 0, "%s\'s face becomes twisted with fury!", GetName());
break;
}
case discFellstrike: { // Duelist/Innerflame/Fellstrike
// monk level 56
// rogue level 59
// warrior level 58
// 12 second duration
// 30 minute reuse
// min 4*base hand/weapon damage
if ( (GetClass() == MONK && GetLevel() <= 55)
||(GetClass() == WARRIOR && GetLevel() <= 58)
||(GetClass() == ROGUE && GetLevel() <= 59)
) return;
duration = 12;
reuse = 60*30;
entity_list.MessageClose(this, false, 100, 0, "%s\'s muscles bulge with force of will!", GetName());
break;
}
case discBlindingSpeed: { // Blindingspeed/Hundredfist
// rogue level 58
// monk level 57
// 15 second duration
// 30 minute reuse
if ( (GetClass() == MONK && GetLevel() <= 58)
||(GetClass() == ROGUE && GetLevel() <= 57)
) return;
//disc_timer.Start(1000*60*30);
//disc_elapse.Start(1000*15);
duration = 15;
reuse = 60*30;
Message(0, "This discipline not implemented..");
break;
}
case discDeadeye: { // Deadeye/Charge
// warrior level 53
// rogue level 54
// 14 second duration
// 30 minute reuse
if ( (GetClass() == WARRIOR && GetLevel() <= 53)
||(GetClass() == ROGUE && GetLevel() <= 54)
) return;
duration = 14;
reuse = 60*30;
entity_list.MessageClose(this, false, 100, 0, "%s feels unstopable!", GetName());
break;
}
// Warrior
case discEvasive: { // Evasive
// level 52
// 3 minute duration
// 15 minute reuse
// +35% avoidance
// -15% out
duration = 3*60;
reuse = 15*60;
break;
}
case discMightystrike: { // Mightystrike
// level 54
// 10 second duration
// 1 hour reuse
// Auto crit
duration = 10;
reuse = 60*60;
break;
}
case discDefensive: { // Defensive
// level 55
// 3 minute duration
// 15 minute reuse, 10 after 60
// +35% mitigation
// -15% out
duration = 3*60;
if(level > 59)
reuse = 10*60;
else
reuse = 15*60;
break;
}
case discPrecise: { // Precise
// level 57
// 3 minute duration
// 30 minute reuse
// -15% avoidance
// +35% out
duration = 3*60;
reuse = 30*60;
break;
}
case discAggressive: { // Aggressive
// level 60
// 3 minute duration
// 27 minute reuse
// -15% mitigation
// +35% out
duration = 3*60;
reuse = 27*60;
break;
}
// Monk
case discStonestance: { // Stonestance
// level 51
duration = 12;
if(level > 59)
reuse = 3*60;
else
reuse = 12*60;
break;
}
case discThunderkick: { // Thunderkick
// level 52
if(level > 59)
reuse = 1*60;
else
reuse = 7*60;
duration = 5*60; //hack for now, checked in combat and expired once used.
break;
}
case discVoidance: { // Voidance
// level 54
if(level > 59)
reuse = 54*60;
else
reuse = 60*60;
duration = 8;
break;
}
case discSilentfist: { // Silentfist
// level 59
// 6-7 minute reuse
// Dragon punch damage bonus
// Chance to stun
if(level > 59)
reuse = 6*60;
else
reuse = 7*60;
duration = 5*60; //hack for now, checked in combat and expired once used.
break;
}
case discAshenhand: { // Ashenhand
// level 60
// 72 minute reuse
// Eagle Strike damage bonus
// Chance to slay
reuse = 72*60;
duration = 5*60; //hack for now, checked in combat and expired once used.
break;
}
// Rogue
case discNimble: { // Nimble
// level 55
// 12 second duration
// 30 minute reuse
// Auto dodge
if(level > 59)
reuse = 25*60;
else
reuse = 30*60;
duration = 12;
break;
}
case discKinesthetics: { // Kinesthetics
// level 57
// 18 second duration
// 30,27 minute reuse
// Auto dualwield
// Auto double attack
if(level > 59)
reuse = 27*60;
else
reuse = 30*60;
duration = 18;
break;
}
// Paladin
case discHolyforge: { // Holyforge
// level 55
// 2 minute duration
// 72 minute reuse
// Crit/Crip undead
// +15% to crit chance
if(level > 59)
reuse = 65*60;
else
reuse = 72*60;
duration = 5*60;
break;
}
case discSanctification: { // Sanctification
// level 60
// 10 second duration
// 72 minute reuse
// Spell immunity
reuse = 72*60;
duration = 15;
break;
}
// Ranger
case discTrueshot: { // Trueshot
// level 55
// 2 minute duration
// 72 minute reuse
// Max to two times max bow damage
// +15% to hit
if(level > 59)
reuse = 67*60;
else
reuse = 72*60;
duration = 2*60;
break;
}
case discWeaponshield: { // Weaponshield
// level 60
// 15 second duration
// 72 minute reuse
// auto parry
reuse = 72*60;
duration = 20;
break;
}
// Bard
case discDeftdance: { // Deftdance
// level 55
// 10 second duration
// 72 minute reuse
// auto dodge
// auto dualwield
if(level > 59)
reuse = 67*60;
else
reuse = 72*60;
duration = 10;
break;
}
case discPuretone: { // Puretone
// level 60
// 2 minute duration
// 72 minute reuse
// Auto instrument
reuse = 72*60;
duration = 4*60;
break;
}
// Shadow knight
case discUnholyAura: { // Unholy
// level 55
// 72 minute reuse
// +25% to harmtouch
// -300 to resist
if(level > 59)
reuse = 67*60;
else
reuse = 72*60;
duration = 5*60; //hack for now, checked in combat and expired once used.
break;
}
case discLeechCurse: { // Leech curse
// level 60
// 15 second duration
// 72 minute reuse
// Heal self for each point of melee damage done
reuse = 72*60;
duration = 15;
break;
}
// Default
case 0:{ // Timer request
break;
}
default:
LogFile->write(EQEMuLog::Error, "Unknown Discipline requested by client: %s class: %i Disciline:%i", GetName(), class_,disc_in->disc_id);
return;
}
if(reuse != 0) {
p_timers.Start(pTimerDisciplineReuse, reuse);
//nonpersistent timer for the 'discipline ready' message
disc_timer.Start(1000*reuse);
}
if(duration != 0)
disc_elapse.Start(1000*duration);
disc_inuse = disc_in->disc_id;
}*/
#if 0 // solar: this is old code
/*void EntityList::AESpell(Mob* caster, Mob* center, float dist, uint16 spell_id, bool group)
{
LinkedListIterator<Mob*> iterator(mob_list);
iterator.Reset();
while(iterator.MoreElements()) {
Mob* mob = iterator.GetData();
if (group){
// Client casting group spell with out target group buffs enabled
// Skip non group members
if ( caster->IsClient()
&& !caster->CastToClient()->TGB()
&& GetGroupByMob(mob) != 0
&& !GetGroupByMob(mob)->IsGroupMember(caster)
) {
LogFile->write(EQEMuLog::Debug, "Group spell skipping %s", mob->GetName());
iterator.Advance();
continue;
}
// Client casting group spell with target group buffs enabled
else if ( caster->IsClient()
&& caster->CastToClient()->TGB()
&& GetGroupByMob(mob) != 0
&& GetGroupByMob(mob)->IsGroupMember(caster)
){
LogFile->write(EQEMuLog::Debug, "Group spell TGB on %s's Group", mob->GetName());
GetGroupByMob(mob)->CastGroupSpell(caster, spell_id);
iterator.Advance();
continue;
}
else if ( caster->IsClient()
&& caster->CastToClient()->TGB()
&& GetGroupByMob(mob) == 0
&& mob == center
){
LogFile->write(EQEMuLog::Debug, "Group spell TGB on %s", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
return;
}
}
if (
mob->DistNoZ(*center) <= dist
&& !(mob->IsClient() && mob->CastToClient()->GMHideMe())
&& !mob->IsCorpse()
) {
//cout << "AE Spell Hit: t=" << iterator.GetData()->GetName() << ", d=" << iterator.GetData()->CastToMob()->DistNoRoot(center) << ", x=" << iterator.GetData()->CastToMob()->GetX() << ", y=" << iterator.GetData()->CastToMob()->GetY() << endl;
if (caster == mob) {
// Caster gets the first hit, already handled in spells.cpp
}
#ifdef IPC
else if(caster->IsNPC() && !caster->CastToNPC()->IsInteractive()) {
#else
else if(caster->IsNPC()) {
#endif
// Npc
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard) {
// printf("NPC Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if (mob->IsAIControlled() && spells[spell_id].targettype == ST_AEBard) {
// printf("NPC mgb/aebard spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else {
// printf("NPC AE, fall thru. spell_id:%i, Target type:%x\n", spell_id, spells[spell_id].targettype);
}
}
#ifdef IPC
else if(caster->IsNPC() && caster->CastToNPC()->IsInteractive()) {
// Interactive npc
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard && spells[spell_id].targettype != ST_GroupTeleport) {
// printf("IPC Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if (!mob->IsAIControlled() && (spells[spell_id].targettype == ST_AEBard||group) && mob->CastToClient()->GetPVP() == caster->CastToClient()->GetPVP()) {
if (group && GetGroupByMob(mob) != GetGroupByMob(caster)) {
iterator.Advance();
continue;
}
// printf("IPC mgb/aebard spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else {
// printf("NPC AE, fall thru. spell_id:%i, Target type:%x\n", spell_id, spells[spell_id].targettype);
}
}
#endif
else if (caster->IsClient() && !(caster->CastToClient()->IsBecomeNPC())) {
// Client
if (caster->IsAttackAllowed(mob) && spells[spell_id].targettype != ST_AEBard){
// printf("Client Spell casted on %s\n", mob->GetName());
caster->SpellOnTarget(spell_id, mob);
}
else if(spells[spell_id].targettype == ST_GroupTeleport && mob->IsClient() && mob->isgrouped && caster->isgrouped && entity_list.GetGroupByMob(caster))
{
Group* caster_group = entity_list.GetGroupByMob(caster);
if(caster_group != 0 && caster_group->IsGroupMember(mob))
caster->SpellOnTarget(spell_id,mob);
}
else if (mob->IsClient() && (spells[spell_id].targettype == ST_AEBard||group) && mob->CastToClient()->GetPVP() == caster->CastToClient()->GetPVP()) {
if (group && GetGroupByMob(mob) != GetGroupByMob(caster)) {
iterator.Advance();
continue;
}
else if (mob->IsClient() && spells[spell_id].targettype == ST_AEBard && mob->CastToClient()->GetPVP() == caster->CastToClient()->GetPVP())
caster->SpellOnTarget(spell_id, mob);
#ifdef IPC
else if (mob->IsNPC() && mob->CastToNPC()->IsInteractive()) {
if (group && GetGroupByMob(mob) != GetGroupByMob(caster))
continue;
caster->SpellOnTarget(spell_id, mob);
}
#endif
}
}
else if (caster->IsClient()) {
// Client BecomeNPC
caster->SpellOnTarget(spell_id, mob);
}
}
iterator.Advance();
}
}*/
#endif // solar: old code
/*#if 0
// Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC(uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
*copper = 0;
*silver = 0;
*gold = 0;
*plat = 0;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, mincash, maxcash, avgcoin FROM loottable WHERE id=%i", loottable_id), errbuf, &result)) {
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
uint32 mincash = atoi(row[1]);
uint32 maxcash = atoi(row[2]);
if (mincash > maxcash) {
cerr << "Error in loottable #" << row[0] << ": mincash > maxcash" << endl;
}
else if (maxcash != 0) {
uint32 cash = 0;
if (mincash == maxcash)
cash = mincash;
else
cash = (rand() % (maxcash - mincash)) + mincash;
if (cash != 0) {
uint32 coinavg = atoi(row[3]);
if (coinavg != 0) {
uint32 mincoin = (uint32) (coinavg * 0.75 + 1);
uint32 maxcoin = (uint32) (coinavg * 1.25 + 1);
*copper = (rand() % (maxcoin - mincoin)) + mincoin - 1;
*silver = (rand() % (maxcoin - mincoin)) + mincoin - 1;
*gold = (rand() % (maxcoin - mincoin)) + mincoin - 1;
cash -= *copper;
cash -= *silver * 10;
cash -= *gold * 10;
}
*plat = cash / 1000;
cash -= *plat * 1000;
uint32 gold2 = cash / 100;
cash -= gold2 * 100;
uint32 silver2 = cash / 10;
cash -= silver2 * 10;
*gold += gold2;
*silver += silver2;
*copper += cash;
}
}
}
else {
mysql_free_result(result);
return;
}
mysql_free_result(result);
}
else
{
cerr << "Error in AddLootTableToNPC get coin query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
if (RunQuery(query, MakeAnyLenString(&query, "SELECT loottable_id, lootdrop_id, multiplier, probability FROM loottable_entries WHERE loottable_id=%i", loottable_id), errbuf, &result)) {
safe_delete_array(query);
while ((row = mysql_fetch_row(result))) {
int multiplier = atoi(row[2]);
for (int i = 1; i <= multiplier; i++) {
if ( ((rand()%1)*100) < atoi(row[3])) {
AddLootDropToNPC(atoi(row[1]), itemlist);
}
}
}
mysql_free_result(result);
}
else {
cerr << "Error in AddLootTableToNPC get items query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
return;
}
return;
}
// Called by AddLootTableToNPC
// maxdrops = size of the array npcd
void ZoneDatabase::AddLootDropToNPC(uint32 lootdrop_id, ItemList* itemlist) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
// This is Wiz's updated Pool Looting functionality. Eventually, the database format should be moved over to use this
// or implemented to support both methods. (A unique identifier in lootable_entries indicates to roll for a pool item
// in another table.
#ifdef POOLLOOTING
uint32 chancepool = 0;
uint32 items[50];
uint32 itemchance[50];
uint16 itemcharges[50];
uint8 i = 0;
for (int m=0;m < 50;m++)
{
items[m]=0;
itemchance[m]=0;
itemcharges[m]=0;
}
if (RunQuery(query, MakeAnyLenString(&query, "SELECT lootdrop_id, item_id, item_charges, equip_item, chance FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc", lootdrop_id), errbuf, &result))
{
safe_delete_array(query);
while (row = mysql_fetch_row(result))
{
items[i] = atoi(row[1]);
itemchance[i] = atoi(row[4]) + chancepool;
itemcharges[i] = atoi(row[2]);
chancepool += atoi(row[4]);
i++;
}
uint32 res;
i = 0;
if (chancepool!=0) //avoid divide by zero if some mobs have 0 for chancepool
{
res = rand()%chancepool;
}
else
{
res = 0;
}
while (items[i] != 0)
{
if (res <= itemchance[i])
break;
else
i++;
}
const Item_Struct* dbitem = database.GetItem(items[i]);
if (dbitem == 0)
{
LogFile->write(EQEMuLog::Error, "AddLootDropToNPC: dbitem=0, item#=%i, lootdrop_id=%i", items[i], lootdrop_id);
}
else
{
//printf("Adding item2: %i",item->item_id);
//cout << "Adding item to Mob" << endl;
ServerLootItem_Struct* item = new ServerLootItem_Struct;
item->item_id = dbitem->ItemNumber;
item->charges = itemcharges[i];
item->equipSlot = 0;
(*itemlist).Append(item);
}
mysql_free_result(result);
}
#else
if (RunQuery(query, MakeAnyLenString(&query, "SELECT lootdrop_id, item_id, item_charges, equip_item, chance FROM lootdrop_entries WHERE lootdrop_id=%i order by chance desc", lootdrop_id), errbuf, &result))
{
safe_delete_array(query);
while ((row = mysql_fetch_row(result)))
{
uint8 LootDropMod=1; // place holder till I put it in a database variable to make it configurable.
if( (rand()%100) < ((atoi(row[4]) * LootDropMod)) )
{
uint32 itemid = atoi(row[1]);
const Item_Struct* dbitem = database.GetItem(itemid);
if (dbitem == 0)
{
LogFile->write(EQEMuLog::Error, "AddLootDropToNPC: dbitem=0, item#=%i, lootdrop_id=%i", itemid, lootdrop_id);
}
else
{
printf("Adding item: %i",item->ItemNumber);
ServerLootItem_Struct* item = new ServerLootItem_Struct;
item->item_id = dbitem->item_id;
item->charges = atoi(row[2]);
item->equipSlot = 0;
(*itemlist).Append(item);
}
//mysql_free_result(result);
//return;
}
}
mysql_free_result(result);
}
#endif
else
{
LogFile->write(EQEMuLog::Error, "Error in AddLootDropToNPC query '%s' %s", query, errbuf);
safe_delete_array(query);
return;
}
return;
}
#endif*/