OK here we go.
I have looked through the current osirose SVN and compared it to my osprose code.
I assume that by NPCVar you mean ObjVar[0] which is in fact used to control events and stuff via AIP. In the LUA (client side) it is referred to as NPCVar0 and in the server it is used to set the variable "eventid" which osirose currently does not support.......
Unfortunately osirose has fallen a long way behind osprose and osrose rev 81 in the way it handles AIP so this might get a bit complicated and messy. I am going to attempt to transfer the code from osprose into osirose and tell you exactly what I did here to make it work.
here goes.
First we add handling for the eventid variable in the CNPCData structure
in datatypes.h struct CNPCData find
- UINT aggresive;
- UINT shp;
- UINT dialogid;
After, add
Now we will just transplant a complete GM command over from osprose. You will probably need to modify the required access level since i have it hard coded at 300 right now.
in gmcommands.cpp find
-
- else
- {
- Log( MSG_WARNING, "Invalid GM Command '%s' by '%s'", command, thisclient->CharInfo->charname);
- }
- return true;
BEFORE, add
-
- else if (strcmp(command, "dialog")==0 && thisclient->Session->accesslevel >= 300)
- {
- //can be a very dangerous tool to use
- UINT npc;
- UINT dialog;
- UINT eventid;
- if ((tmp = strtok(NULL, " "))==NULL)return true;
- npc = atoi(tmp);
- if ((tmp = strtok(NULL, " "))==NULL)return true;
- dialog = atoi(tmp);
- if ((tmp = strtok(NULL, " "))==NULL)return true;
- eventid = atoi(tmp);
- if(thisclient->ChangeDialog(npc, dialog, eventid))
- {
- char buffer2[200];
- sprintf ( buffer2, "dialog for npc %i set to %i event set to %i", npc, dialog, eventid );
- SendPM(thisclient, buffer2);
- }
- else
- {
- char buffer2[200];
- sprintf ( buffer2, "dialog and event for npc %i not changed", npc );
- SendPM(thisclient, buffer2);
- }
- }
this bit gets kind of messy because it really requires AIP to be able to change the eventid of an NPC and osirose doesn't have very complete AIP handling yet.
go to Worldpackets.cpp and find function
bool CWorldServer::pakSpawnNPC( CPlayer* thisclient, CNPC* thisnpc )We are going to mess around with the way NPCs are spawned a bit.
Find this
- if (thisnpc->npctype == 1115) ADDBYTE( pak, GServer->Config.Cfmode ) // Burland Clan Field open/close
- else ADDBYTE ( pak, 0 );
This sets up a special case for Burtland who owns the clan fields. It adds a byte to the 0x791 packet that spawns an NPC. It will either the value held in Config.Cfmode or zero depending on whether the npc is Burtland or not.
This byte is the one that the client reads into NPCVar0 and is used to activate or modify events that the NPC is capable of handling. We need to change this so that the value that we set in the new GM command will be sent instead.
This code will screw up the Config.Cfmode value completely so bear that in mind. The Config value will no longer set the clanfield to open or closed at boot up. You will however, be able to open or close clanfields manually from within the game with your GM command.
Well anyway, replace that bit of code with this. i just commented out the original so that you can switch back easily.
-
- //if (thisnpc->npctype == 1115) ADDBYTE( pak, GServer->Config.Cfmode ) // Burland Clan Field open/close
- // else ADDBYTE ( pak, 0 );
- if(thisnpc->thisnpc->eventid != 0)
- {
- ADDBYTE (pak, thisnpc->thisnpc->eventid);
- }
- else
- {
- ADDBYTE( pak, 0 );
- }
Now we need to go and set up the header for ChangeDialog since we are about to change the way it works a little
in Player.h, find
-
- bool ChangeDialog( unsigned int npc, unsigned int dialog );
-
Replace with this. Once again, i just commented the original so that you can switch back easily.
-
- //bool ChangeDialog( unsigned int npc, unsigned int dialog );
- bool ChangeDialog( unsigned int npc, unsigned int dialog, unsigned int eventid = 0 );
-
Now we actually modify the changedialog function so go find this in Playerfunctions.cpp
- bool CPlayer::ChangeDialog(unsigned int npc, unsigned int dialog )
Replace the entire function with this. (Again, i left the original code in place but commented out. You can delete it once you are good and happy with the new way that stuff works now.
-
- /*bool CPlayer::ChangeDialog(unsigned int npc, unsigned int dialog )
- {
- CMap* map = GServer->MapList.Index[Position->Map];
- for(unsigned i=0; i<map->NPCList.size(); i++)
- {
- CNPC* thisnpc = map->NPCList.at(i);
-
- if(thisnpc->thisnpc->id = npc)
- {
- CNPC* newnpc = thisnpc;
- map->DeleteNPC(thisnpc);
- newnpc->thisnpc->dialogid = dialog;
- GServer->pakSpawnNPC (this, newnpc);
- }
- }
- return true;
- }*/
-
- bool CPlayer::ChangeDialog(unsigned int npc, unsigned int dialog, unsigned int eventid )
- {
- CMap* map = GServer->MapList.Index[Position->Map];
- if(map == NULL)
- return true;
- for(unsigned i=0; i<map->NPCList.size(); i++)
- {
- CNPC* thisnpc = map->NPCList.at(i);
-
- if(thisnpc->npctype == npc)
- {
- //Log(MSG_INFO,"Found NPC %i with dialog %i",thisnpc->npctype, thisnpc->thisnpc->dialogid);
- CNPC* newnpc = thisnpc;
- this->ClearObject( thisnpc->clientid );
- newnpc->thisnpc->dialogid = dialog;
- newnpc->thisnpc->eventid = eventid;
- GServer->ObjVar[npc][0] = eventid;
- VisibleNPCs.push_back( newnpc );
- GServer->pakSpawnNPC( this, newnpc );
- }
- }
- return true;
- }
Damn it...
This is getting more involved than I even thought it would. Need to add more definitions
In worldserver.h, find
- fpAiCond aiCondFunc[35];
- fpAiAct aiActFunc[40];
after, add
-
- int ObjVar[2000][20]; //NPC variables used in AI
Well it actually compiles correctly at this point so it should work for you.
I have no way to test it though because i don't have an operational osirose server or client to try it out with.
The AIP still isn't going to make this NPCVar change at any time because it simply doesn't have handling for it but at least now that you have the ObjVar[][] structure set up, it will be relatively easy to port code over from osprose or osrose rev 81 if you are handy with coding stuff.
Right now. how to use the new GM command?
It is composed of 3 parts. npc, dialog and eventid
/dialog[npcid][dialogid][eventid]lets say we want to make Judy in Zant say something different.
her NPC number is 1201 (you can get this from LIST_NPC.STB. It's the row number)
Her normal dialog is 305 (you can get this from list_npc sql table)
her eventid defaults to 0 as do all the NPCs but if you care to set it to a different number, who knows what might happen
Look in the CON file LUA scripts to find out what NPCVar0 needs to be set to in order to make stuff happen.
try setting
/dialog 1201 305 3 then talk to judy
If it all worked right (and you have the spring quest in your files) then she should send you off to get cherry blossoms from cherry smoulies.
2 will start a valentines day quest. there are loads more in there (EM01-101.CON is where Judy's stuff is stored)
To open clan fields you need to type
/dialog 1115 215 2To close them again type
/dialog 1115 215 0Give it a try and see what fun stuff you can find out. be careful though. It's possible to really screw up you quests if you take one of these out of order.