Go Back   EQEmulator Home > EQEmulator Forums > Archives > Archive::Development > Archive::Development

Archive::Development Archive area for Development's posts that were moved here after an inactivity period of 90 days.

Reply
 
Thread Tools Display Modes
  #1  
Old 01-30-2002, 02:35 AM
foley
Fire Beetle
 
Join Date: Jan 2002
Posts: 12
Default Knock knock

That's right, my door code is ready to be released for feedback. Basic doors work, there is support for locked doors, though the zone data packets that are sent when zoning do not tell you if a door is locked or what the key is, so we will have to manually enter this data into the database. Also "triggered" objects are supported, ie. elevators, but again, this information isn't sent in the zone data packets so we will have to enter this information manually. Also, I noticed that on the live servers when you open double doors, you only need to click on one of the doors to open them both. I think we can accomplish this using the "trigger" code, but for now, you will have to click on both doors in a double door set to open them.

Directions
1. Download this zip file zoneobjects.zip
2. Unzip this file, put the ZoneObject.h and ZoneObject.cpp file into the zone directory of your EQEmu Source Code and put the ZoneObjects.sql file into your mysql\bin directory.
3. start up mysql.exe in your mysql\bin directory and type use eq (or whatever your database name is).
4. type source zoneobjects.sql (you should get a bunch of OKs indicating successful database inserts)
5. follow the coding directions below to update zone.exe
Reply With Quote
  #2  
Old 01-30-2002, 02:39 AM
foley
Fire Beetle
 
Join Date: Jan 2002
Posts: 12
Default

Code Directions
Add Zoneobject.cpp and ZoneObject.h to your project.

Add the following line to Client::Process() inside the if (Connected()) block:
zone->CheckZoneObjects();

Modify the case CLIENT_CONNECTING4: { in client_process.cpp block to look like the following:
if (app->opcode == 0x0a20)
{
cout << "Login packet 4" << endl;

APPLAYER* outapp;

ZoneObject_Struct *zos;
ZoneObject_Struct *dzos;
int numzoneobjects,deflatedsize;

numzoneobjects=zone->GetZoneObjects(zos);
if(numzoneobjects>0)
{
dzos=new ZoneObject_Struct[numzoneobjects];
deflatedsize=DeflatePacket((unsigned char*)(zos), sizeof(ZoneObject_Struct)*numzoneobjects, (unsigned char*)(dzos), sizeof(ZoneObject_Struct)*numzoneobjects);
delete zos;

outapp = new APPLAYER;
outapp->pBuffer = new uchar[deflatedsize+2];
outapp->opcode = 0xf721;
*(int16 *)(outapp->pBuffer)=numzoneobjects;
memcpy((outapp->pBuffer)+2, dzos, deflatedsize);
outapp->size = deflatedsize+2;
packet_manager.MakeEQPacket(outapp);
delete outapp;
delete dzos;
}

outapp = new APPLAYER;
outapp->opcode = 0xd820; // Unknown
outapp->size = 0;
QueuePacket(outapp);
delete outapp;

client_state = CLIENT_CONNECTING5;
break;
}
}


Add the following case to the switch(app->opcode) block that is within the case CLIENT_CONNECTED in client_process.cpp
case OP_ZoneObjectOpenRequest: {
APPLAYER *outapp;
ZoneObjectOpen_Struct *zoos = (ZoneObjectOpen_Struct *)app->pBuffer;
ZoneObject *zo=zone->GetZoneObject(zoos->zoneobject_id);
cout << "zoneobjectid=" << int(zo->GetZoneObjectID()) << " initialstate=" << int(zo->zoneobjectstruct.initialstate) << " item=" << uint32(zoos->item_nr) << endl;
if(zo && zo->zoneobjectstruct.initialstate) // check if open
{
cout << "closing zone object" << endl;
outapp = new APPLAYER;
outapp->opcode=OP_ZoneObjectOpen;
outapp->size=2;
outapp->pBuffer=new uchar[outapp->size];
outapp->pBuffer[0]=zoos->zoneobject_id;
outapp->pBuffer[1]=0x03; // seems to say 'close'

entity_list.QueueCloseClients(this,outapp,true); // tell other clients
packet_manager.MakeEQPacket(outapp); // tell client who closed the object
delete outapp;

zo->zoneobjectstruct.initialstate=0;
zone->CloseZoneObject(zoos->zoneobject_id);
}
else if(zo && (zoos->item_nr==0xffff || zo->GetKeyNumber()==zoos->item_nr || zoos->item_nr==0x0000))
{
cout << "opening zone object" << endl;
outapp = new APPLAYER;
outapp->opcode=OP_ZoneObjectOpen;
outapp->size=2;
outapp->pBuffer=new uchar[outapp->size];
outapp->pBuffer[0]=zoos->zoneobject_id;
outapp->pBuffer[1]=0x02; // seems to say 'open'
if(zoos->item_nr==0x0000)
{
cout << "auto close request?" << endl;
outapp->pBuffer[1]=0x03;
}

entity_list.QueueCloseClients(this,outapp,true); // tell other clients
packet_manager.MakeEQPacket(outapp); // tell client who opened the door
delete outapp;

zo->zoneobjectstruct.initialstate=1;
zone->AddOpenedZoneObject(zoos->zoneobject_id, zo->opentimer);
}
else if(zo)
{
Message(13, "It's locked and you're not holding the key.");
break;
}
if(zo)
{
uint32 triggerid=zo->trigger_id;
if(triggerid!=65535)
{
ZoneObject *tzo=zone->GetZoneObject(triggerid);
if(tzo && tzo->zoneobjectstruct.initialstate && !zone->GetZoneObjectStatus(triggerid)) // check if open
{
cout << "closing triggered object:" << triggerid << endl;
outapp = new APPLAYER;
outapp->opcode=OP_ZoneObjectOpen;
outapp->size=2;
outapp->pBuffer=new uchar[outapp->size];
outapp->pBuffer[0]=triggerid;
outapp->pBuffer[1]=0x03; // seems to say 'close'
entity_list.QueueCloseClients(this,outapp,true); // tell other clients
packet_manager.MakeEQPacket(outapp); // tell client who closed the object
delete outapp;

tzo->zoneobjectstruct.initialstate=0;
zone->AddOpenedZoneObject(triggerid, tzo->opentimer);
}
else if(tzo && !zone->GetZoneObjectStatus(triggerid))
{
cout << "opening triggered object:" << triggerid << endl;
outapp = new APPLAYER;
outapp->opcode=OP_ZoneObjectOpen;
outapp->size=2;
outapp->pBuffer=new uchar[outapp->size];
outapp->pBuffer[0]=triggerid;
outapp->pBuffer[1]=0x02; // seems to say 'open'
entity_list.QueueCloseClients(this,outapp,true); // tell other clients
packet_manager.MakeEQPacket(outapp); // tell client who opened the door
delete outapp;

tzo->zoneobjectstruct.initialstate=1;
zone->AddOpenedZoneObject(triggerid, tzo->opentimer);
}
}
}
break;
}
Reply With Quote
  #3  
Old 01-30-2002, 02:43 AM
foley
Fire Beetle
 
Join Date: Jan 2002
Posts: 12
Default

Add the following functions prototypes to zone.h
public:
int GetZoneObjectStatus(char);
void AddOpenedZoneObject(char, uint32);
void CloseZoneObject(char);
void CheckZoneObjects();
int GetZoneObjects(char *, ZoneObject_Struct*&
ZoneObject *GetZoneObject(char);
private:
int numzoneobjects;
LinkedList<ZoneObject*> ZoneObjects;
LinkedList<ZoneObject*> opened_zone_object_list;

And also add the following include to zone.h
#include "zoneobject.h"

Add the following line to the Zone constructor
numzoneobjects=GetZoneObjectsFromDB();

Add the following function definitions to zone.cpp
int Zone::GetZoneObjectsFromDB() {
char *query = 0;
int buf_len = 256;
int chars = -1;
MYSQL_RES *result;
MYSQL_ROW row;
int numzoneobjects;

while (chars == -1 || chars >= buf_len)
{
if (query != 0)
{
delete[] query;
query = 0;
buf_len *= 2;
}
query = new char[buf_len];
chars = snprintf(query, buf_len, "SELECT * FROM zoneobjects WHERE zonename='%s'", short_name);
}
if (!mysql_query(&database.mysql, query))
{
delete[] query;
result = mysql_store_result(&database.mysql);
if (result)
{
numzoneobjects=int(mysql_num_rows(result));
for(int i=0; i< numzoneobjects; i++)
{
row = mysql_fetch_row(result);
ZoneObject *newzoneobject=new ZoneObject;

strcpy(newzoneobject->zoneobjectstruct.name, row[1]);
newzoneobject->zoneobjectstruct.x=atof(row[2]);
newzoneobject->zoneobjectstruct.y=atof(row[3]);
newzoneobject->zoneobjectstruct.z=atof(row[4]);
newzoneobject->zoneobjectstruct.heading=atof(row[5]);
newzoneobject->zoneobjectstruct.unknown1=atof(row[6]);
newzoneobject->zoneobjectstruct.unknown2=atof(row[7]);
newzoneobject->zoneobjectstruct.zoneobject_id=atoi(row[8]);
newzoneobject->zoneobjectstruct.type=atoi(row[9]);
newzoneobject->zoneobjectstruct.initialstate=atoi(row[10]);
newzoneobject->zoneobjectstruct.holdstateforever=atoi(row[11]);
newzoneobject->zoneobjectstruct.unknown3=atof(row[12]);
newzoneobject->zoneobjectstruct.unknown4=atof(row[13]);
newzoneobject->zoneobjectstruct.unknown5=atof(row[14]);
newzoneobject->zoneobjectstruct.unknown6=atof(row[15]);
newzoneobject->item_nr=atoi(row[16]);
newzoneobject->trigger_id=atoi(row[17]);
newzoneobject->opentimer=atoi(row[18]);
ZoneObjects.Append(newzoneobject);
}
cout << numzoneobjects << " Zone Objects Loaded" << endl;
}
mysql_free_result(result);
}
else
{
cerr << "Error in GetZoneObjects query '" << query << "' " << mysql_error(&database.mysql) << endl;
delete[] query;
}
return numzoneobjects;
}
int Zone::GetZoneObjects(ZoneObject_Struct* &zos)
{
LinkedListIterator<ZoneObject*> iterator(ZoneObjects);

zos = new ZoneObject_Struct[numzoneobjects];
int i=0;
iterator.Reset();
while (iterator.MoreElements())
{
zos[i]=iterator.GetData()->zoneobjectstruct;
iterator.Advance();
i++;
}
return numzoneobjects;
}
int Zone::GetZoneObjectStatus(char zoneobject_id) // Is it open?
{
LinkedListIterator<ZoneObject*> iterator(opened_zone_object_list);

iterator.Reset();
while (iterator.MoreElements())
{
if(iterator.GetData()->GetZoneObjectID()==zoneobject_id)
return 1;
iterator.Advance();
}
return 0;
}
void Zone::CheckZoneObjects() // If timer has run out, close it
{
LinkedListIterator<ZoneObject*> iterator(opened_zone_object_list);

iterator.Reset();
while (iterator.MoreElements())
{
if(iterator.GetData()->timer->Check())
{
ZoneObject *pzo;
pzo=GetZoneObject(iterator.GetData()->GetZoneObjectID());
if(!pzo->zoneobjectstruct.holdstateforever)
pzo->zoneobjectstruct.initialstate=0;
iterator.RemoveCurrent();
}
iterator.Advance();
}
}
ZoneObject *Zone::GetZoneObject(char zoneobject_id)
{
LinkedListIterator<ZoneObject*> iterator(ZoneObjects);

iterator.Reset();
while (iterator.MoreElements())
{
if(iterator.GetData()->GetZoneObjectID()==zoneobject_id)
return iterator.GetData();
iterator.Advance();
}
return 0;
}
void Zone::AddOpenedZoneObject(char zoneobject_id, uint32 opentimer)
{
ZoneObject *newzoneobject=new ZoneObject;
newzoneobject->SetZoneObjectID(zoneobject_id);
newzoneobject->timer=new Timer(opentimer);
opened_zone_object_list.Append(newzoneobject);
}
void Zone::CloseZoneObject(char zoneobject_id)
{
LinkedListIterator<ZoneObject*> iterator(opened_zone_object_list);

iterator.Reset();
while (iterator.MoreElements())
{
if(iterator.GetData()->GetZoneObjectID()==zoneobject_id)
{
iterator.RemoveCurrent();
return;
}
iterator.Advance();
}
}

Add the Following 2 lines to eq_opcodes.h
#define OP_ZoneObjectOpenRequest 0x8d20
#define OP_ZoneObjectOpen 0x8e20

Add the Following structs to eq_packet_structs.h
struct ZoneObject_Struct
{
char name[16]; // Filename of object? Determines what the object looks like
float x;
float y;
float z;
float heading;
float unknown1;
float unknown2;
char zoneobject_id; // uniquely identifies the object within the zone
char type; // determines animation (can do cool things with this)
char initialstate; // is it initially open,spinniing etc.
char holdstateforever; // stay open forever, or return to "closed" after 11 seconds
char unknown3;
char unknown4;
char unknown5;
char unknown6;
};

struct CompressedZoneObject_Struct
{
uint16 count; // number of objects
struct ZoneObject_Struct *zoneobjects;
};

struct ZoneObjectOpen_Struct
{
char zoneobject_id; // id within the zone of the door
char action; // 01
char placeholder[2];
uint16 item_nr; // unique item number player is holding(key)
char placeholder2[2];
char unknown[2];
char placeholder3[2];
};
Reply With Quote
  #4  
Old 01-30-2002, 03:13 AM
foley
Fire Beetle
 
Join Date: Jan 2002
Posts: 12
Default

In case anyone was wondering the following zones are included in the data set.
Antonica:
All EXCEPT Cazic-Thule, Arena, and Beholder's Maze
Faydwer:
All EXCEPT Kedge Keep and Unrest
Odus:
All EXCEPT Erud's Crossing and Stonebrunt Mountains
Kunark:
None
Velious:
None
Luclin:
None
Planes:
None
Reply With Quote
  #5  
Old 01-30-2002, 03:25 AM
darvik
Fire Beetle
 
Join Date: Jan 2002
Posts: 21
Default

So , will this allow things such as teleporters to work also? Like say the firepots in TD (If they were put in the db) ?
Reply With Quote
  #6  
Old 01-30-2002, 05:45 AM
foley
Fire Beetle
 
Join Date: Jan 2002
Posts: 12
Default

Quote:
Originally Posted by darvik
So , will this allow things such as teleporters to work also? Like say the firepots in TD (If they were put in the db) ?
No I don't believe this will accomplish that, though I will have to check into that.
Reply With Quote
  #7  
Old 01-30-2002, 06:52 AM
Nefarious
Fire Beetle
 
Join Date: Jan 2002
Posts: 18
Default

nice foley =)

now.. to see if it works... =p
__________________
<!||Nefarious||!>
"Just because I'm smart, doesn't mean i can't act stupid"
Reply With Quote
  #8  
Old 01-31-2002, 01:05 AM
Pyrotek
Sarnak
 
Join Date: Jan 2002
Posts: 97
Default

Looks good, more tables of info to maintain. :/
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 01:37 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3