Events?

Place your questions about osirose here

Moderators: osRose dev team, ospRose dev team, osiRose dev team, Moderators

Re: Events?

Postby PurpleYouko on Fri Nov 07, 2008 10:11 pm

Actually I released this code about a year ago :lol:

It's already implemented in rev 81

I'm pretty sure I dropped it in the forums somewhere as a general release.

I have actually abandoned developing it since then though. With the advent of some decent editors along with QSD and AIP handling, it's pretty much pointless. We can now make the events work the way they do in the official servers.
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Events?

Postby PurpleYouko on Fri Nov 07, 2008 10:28 pm

Seems it was posted in a private scripts area.

here it is again for anyone interested.


here it is at last. the custom events/telegates code :)

I just got through making a minor alteration to the code so that type 10 items can be used as collect items. Previously only type 12 items could be used. The change is untested so far but i see no reason why it should present any problems.

open Startup.cpp.
Insert between existing functions. (anywhere you like)
  1.  
  2. bool CWorldServer::LoadCustomTeleGate()
  3. {
  4.     Log( MSG_INFO, "Loading Custom Telegate data" );    
  5.     MYSQL_ROW row;    
  6.     MYSQL_RES *result = DB->QStore("SELECT id,sourcex,sourcey,sourcemap,destx,desty,destmap,radius,active FROM list_customgates");  
  7.     CustomGateList.clear();
  8.     if(result==NULL)
  9.     {
  10.         DB->QFree( );
  11.         return false;
  12.     }
  13.     while( row = mysql_fetch_row(result) )
  14.     {
  15.         CCustomGate* thisgate = new (nothrow) CCustomGate;
  16.         if(thisgate == NULL)
  17.         {
  18.             Log(MSG_ERROR, "Error allocing memory       " );
  19.             DB->QFree( );
  20.             return false;          
  21.         }
  22.         thisgate->id = atoi(row[0]);
  23.         thisgate->source.x = (float)atof(row[1]);
  24.         thisgate->source.y = (float)atof(row[2]);
  25.         thisgate->sourcemap = atoi(row[3]);
  26.         thisgate->dest.x = (float)atof(row[4]);
  27.         thisgate->dest.y = (float)atof(row[5]);
  28.         thisgate->destmap = atoi(row[6]);
  29.         thisgate->radius = atoi(row[7]);
  30.         thisgate->active = atoi(row[8]);
  31.         CustomGateList.push_back(thisgate);        
  32.     }
  33.     DB->QFree( );  
  34.     return true;
  35. }


Still in startup.cpp
insert (same as before)
  1.  
  2. bool CWorldServer::LoadCustomEvents( )
  3. {
  4.     Log( MSG_LOAD, "Custom Events data            " );    
  5.     MYSQL_ROW row;
  6.     MYSQL_RES *result = DB->QStore("SELECT id,eventtype,npcname,x,y,map,radius,active,pc1,pc2,pc3,pc4,pc5,pc6,pc7,pc8,pc9,pc10,pt1,pt2,pt3,pt4,pt5,pt6,pt7,pt8,pt9,pt10,pi1,pi2,pi3,pi4,pi5,pi6,pi7,pi8,pi9,pi10,pn1,pn2,pn3,pn4,pn5,pn6,pn7,pn8,pn9,pn10,script1,script2,script3,script4,itemname,collecttype,collectnum,level FROM list_customevents");
  7.     CustomEventList.clear();
  8.     if(result==NULL)
  9.     {
  10.         DB->QFree( );
  11.         return false;
  12.     }  
  13.     int i;      
  14.     while( row = mysql_fetch_row(result) )
  15.     {  
  16.         CCustomEvent* thisevent = new (nothrow) CCustomEvent;
  17.         if(thisevent == NULL)  
  18.         {
  19.             Log(MSG_ERROR, "Error allocing memory" );
  20.             DB->QFree( );
  21.             return false;
  22.         }
  23.         thisevent->id = atoi(row[0]);
  24.         thisevent->eventtype = atoi(row[1]);
  25.         strcpy(thisevent->npcname,row[2]);
  26.         thisevent->location.x = (float)atof(row[3]);
  27.         thisevent->location.y = (float)atof(row[4]);
  28.         thisevent->map = atoi(row[5]);
  29.         thisevent->radius = atoi(row[6]);
  30.         thisevent->active = atoi(row[7]);
  31.         for(i=1;i<11;i++)
  32.         {
  33.             thisevent->prizecost[i] = atoi(row[7+i]);
  34.         }
  35.         for(i=1;i<11;i++)
  36.         {
  37.             thisevent->prizetype[i] = atoi(row[17+i]);
  38.         }
  39.         for(i=1;i<11;i++)
  40.         {
  41.             thisevent->prizeid[i] = atoi(row[27+i]);
  42.         }
  43.         for(i=1;i<11;i++)
  44.         {
  45.             strcpy(thisevent->prizename[i].prizename ,row[37+i]);
  46.         }
  47.         strcpy(thisevent->script1,row[48]);
  48.         strcpy(thisevent->script2,row[49]);
  49.         strcpy(thisevent->script3,row[50]);
  50.         strcpy(thisevent->script4,row[51]);
  51.         strcpy(thisevent->itemname,row[52]);
  52.         thisevent->collecttype = atoi(row[53]);
  53.         thisevent->collectid = atoi(row[54]);
  54.         thisevent->level = atoi(row[55]);
  55.         CustomEventList.push_back(thisevent);
  56.     }
  57.     DB->QFree( );
  58.     Log( MSG_INFO, "Custom Event data loaded" );
  59.     return true;
  60. }


open Worldserver.h
find
  1.  
  2.  bool LoadTeleGateData( );
  3.  

after, add
  1.  
  2. bool LoadCustomTeleGate( );
  3. bool LoadCustomEvents( );
  4.  


Still in Worldserver.h, find
  1.  
  2. vector<CTeleGate*>      TeleGateList;           // Telegates List
  3.  

after, add
  1.  
  2. vector<CCustomGate*>    CustomGateList;         // Custom Telegate list
  3.         vector<CCustomEvent*>   CustomEventList;        //Custom events list
  4.  


still in WorldServer.h
find
  1.  
  2. bool SendGlobalMSG( CPlayer* thisclient, char msg[200] );
  3.  

after, add
  1.  
  2. bool NPCMessage( CPlayer* thisclient, char msg[200], char npc[50] );
  3.  


open Worldserver.cpp
find

After, add
  1.  
  2. // PY custom events start
  3.     LoadCustomTeleGate( );
  4.     LoadCustomEvents( );
  5.     // PY custom events end
  6.  


Open Worldmap.h
find
  1.  
  2. vector<CTeleGate*>          TeleGateList;     // Telegates from this map
  3.  

after add
  1.  
  2. vector<CCustomGate*>        CustomGateList;   //Custom telegate list
  3.     vector<CCustomEvent*>       CustomEventList;  //Custom events list
  4.  

I don't quite know why this has to be registered in worldmap.h but i couldn't get it to work without it.

open playerfunctions.cpp
Somewhere (any place you like) add
  1.  
  2. bool CPlayer::CheckPortal()
  3. {
  4.     //CPlayer* thisclient = GServer->GetClientByCharName( CharInfo->charname );
  5.     clock_t etime = clock() - lastportalchecktime;      
  6.    
  7.     if ( etime >= 2 * CLOCKS_PER_SEC )
  8.     {  
  9.         lastportalchecktime = clock();
  10.         for(int i=0;i<GServer->CustomGateList.size();i++)
  11.         {
  12.             CCustomGate* thisgate = GServer->CustomGateList.at(i);
  13.             if(!thisgate->active)
  14.                 continue;
  15.             if(thisgate->sourcemap == Position->Map && thisgate->active == true)
  16.             {
  17.                 float xmin = thisgate->source.x - thisgate->radius;
  18.                 float xmax = thisgate->source.x + thisgate->radius;
  19.                 float ymin = thisgate->source.y - thisgate->radius;
  20.                 float ymax = thisgate->source.y + thisgate->radius;
  21.                 if(Position->current.x >= xmin && Position->current.x <= xmax && Position->current.y >= ymin && Position->current.y <=ymax)
  22.                 {
  23.                     fPoint coord;
  24.                     coord.x = thisgate->dest.x;
  25.                     coord.y = thisgate->dest.y;
  26.                     GServer->MapList.Index[thisgate->destmap]->TeleportPlayer( this, coord, false );
  27.                     return true;                  
  28.                 }
  29.             }
  30.         }  
  31.     }
  32.     return true;
  33. }
  34. bool CPlayer::CheckEvents()
  35. {
  36.    //CPlayer* thisclient = GServer->GetClientByCharName( CharInfo->charname );
  37.    
  38.    clock_t etime = clock() - lastEventTime;
  39.    clock_t rtime = clock() - RefreshEventTimer;
  40.    if ( etime >= 2 * CLOCKS_PER_SEC )
  41.    {
  42.        lastEventTime = clock( );
  43.        for(int i=0;i<GServer->CustomEventList.size();i++)
  44.        {
  45.            CCustomEvent* thisevent = GServer->CustomEventList.at(i);  
  46.            if(thisevent->map == Position->Map && thisevent->active == 1)
  47.            {
  48.                float xmin = thisevent->location.x - thisevent->radius;
  49.                float xmax = thisevent->location.x + thisevent->radius;
  50.                float ymin = thisevent->location.y - thisevent->radius;
  51.                float ymax = thisevent->location.y + thisevent->radius;
  52.                if(Position->current.x >= xmin && Position->current.x <= xmax && Position->current.y >= ymin && Position->current.y <= ymax)
  53.                {    
  54.                    //first interrogate the player's inventory to see if they have any of the necessary items.
  55.                    //Log( MSG_INFO, "Found the right event details. Event = %i",CharInfo->ActiveEvent );
  56.                    if(CharInfo->ActiveEvent == true)
  57.                        continue;
  58.                    CharInfo->ActiveEvent = true;
  59.                    //Log( MSG_INFO, "event = %i",CharInfo->ActiveEvent );
  60.                    bool hasitem = false;
  61.                    char buffer2[200];
  62.                    int itemcount = 0;
  63.                    for(int slot=71;slot<103;slot++)
  64.                    {
  65.                        if(items[slot].itemtype == thisevent->collecttype && items[slot].itemnum == thisevent->collectid && items[slot].count >0)
  66.                        {
  67.                            //player has some of the items needed for this event
  68.                            hasitem = true;  
  69.                            itemcount +=  items[slot].count;                    
  70.                        }      
  71.                    }
  72.                    // fetch type event. Collect items and exchange for rewards
  73.                    // Also used for pure information that requires no items
  74.                    if (thisevent->eventtype == 0)
  75.                    {
  76.                        if (hasitem == true) //call this script if player has some of the items
  77.                        {
  78.                            if(itemcount < thisevent->prizecost[1])
  79.                            {
  80.                                sprintf ( buffer2, "I'm sorry but you haven't collected enough %s to earn a reward yet. Please collect more", thisevent->itemname );
  81.                                GServer->NPCMessage(this, buffer2, thisevent->npcname);                
  82.                            }
  83.                            else
  84.                            {  
  85.                                sprintf ( buffer2, "Oh you have collected enough %s to earn a reward.",thisevent->itemname );
  86.                                GServer->NPCMessage(this, buffer2, thisevent->npcname);
  87.                                sprintf ( buffer2, "%s", thisevent->script2 ); //invitation to a prize script
  88.                                GServer->NPCMessage(this, buffer2, thisevent->npcname);
  89.                                for(int j=0;j<10;j++)
  90.                                {
  91.                                    if(itemcount >= thisevent->prizecost[j] && thisevent->prizecost[j] != 0)
  92.                                    {
  93.                                        sprintf ( buffer2, "Item %i: %s. %i %s and its yours", j,thisevent->prizename[j].prizename,thisevent->prizecost[j],thisevent->itemname );
  94.                                        GServer->NPCMessage(this, buffer2, thisevent->npcname);        
  95.                                    }
  96.                                }
  97.                            }
  98.                        }
  99.                        else // call this if the player doesn't have any
  100.                        {    
  101.                            sprintf ( buffer2, "%s", thisevent->script1 ); //event introduction script
  102.                            GServer->NPCMessage(this, buffer2, thisevent->npcname);
  103.                            Log( MSG_INFO, "Custom event script1 sent for type 0 event" );  
  104.                        }
  105.                    }
  106.                    // quest type event
  107.                    // used if a specific item unlocks a different behaviour from the NPC
  108.                    if (thisevent->eventtype == 1)
  109.                    {
  110.                        if(hasitem == false)
  111.                        {
  112.                            sprintf ( buffer2, "%s", thisevent->script1 ); //send this script if the player has no prerequisite item for the next step of the quest
  113.                            GServer->NPCMessage(this, buffer2, thisevent->npcname);
  114.                            Log( MSG_INFO, "Custom event script1 sent for type1 event" );          
  115.                        }                        
  116.                    }
  117.                }
  118.                else
  119.                {
  120.                    CharInfo->ActiveEvent = false;    
  121.                }
  122.            }
  123.        }
  124.    }
  125.    return true;  
  126. }
  127.  
  128. bool CPlayer::PrizeExchange(CPlayer* thisclient, UINT prizeid)
  129. {
  130.     //first find which, if any, event area the player is currently in.
  131.     Log( MSG_INFO, "Prize function called" );
  132.     char buffer2[200];
  133.     for(int i=0;i<GServer->CustomEventList.size();i++)
  134.     {
  135.         CCustomEvent* thisevent = GServer->CustomEventList.at(i);  
  136.         if(thisevent->map == Position->Map && thisevent->active == 1)
  137.         {
  138.             float xmin = thisevent->location.x - thisevent->radius;
  139.             float xmax = thisevent->location.x + thisevent->radius;
  140.             float ymin = thisevent->location.y - thisevent->radius;
  141.             float ymax = thisevent->location.y + thisevent->radius;
  142.             if(Position->current.x >= xmin && Position->current.x <= xmax && Position->current.y >= ymin && Position->current.y <= ymax)
  143.             {
  144.                 //well we found the correct event
  145.                 int cost = thisevent->prizecost[prizeid];
  146.                 int type = thisevent->prizetype[prizeid];
  147.                 int id = thisevent->prizeid[prizeid];
  148.                 if (type == 0)return true; //just in case somebody puts in an invalid number.
  149.                 //now find if the player has enough items to purchase the prize
  150.                 UINT itemcount = 0;
  151.                 for(int slot=42;slot<101;slot++)
  152.                 {
  153.                     if(items[slot].itemtype == thisevent->collecttype && items[slot].itemnum == thisevent->collectid && items[slot].count > 0)
  154.                     {
  155.                         //player has some of the items needed for this event
  156.                         itemcount += items[slot].count;
  157.                         items[slot].count = 0;
  158.                         ClearItem(items[slot]);  
  159.                         BEGINPACKET( pak, 0x718 );
  160.                         {ADDBYTE( pak, 1 );}
  161.                         ADDBYTE    ( pak, slot);
  162.                         ADDDWORD   ( pak, GServer->BuildItemHead( items[slot] ) );
  163.                         ADDDWORD   ( pak, GServer->BuildItemData( items[slot] ) );
  164.                         client->SendPacket( &pak );                
  165.                     }      
  166.                 }  
  167.                 if(itemcount >= cost)
  168.                 {
  169.                     Log( MSG_INFO, "Itemcount = %i. Cost = %i",itemcount,cost );
  170.                     //OK the player meets the criteria. Now give him the prize and take away the items
  171.                     sprintf ( buffer2, "Your prize has been placed into your inventory.");
  172.                     GServer->NPCMessage(this, buffer2, thisevent->npcname);            
  173.                     bool freeslot = false;
  174.                     int slot;
  175.                     for(slot=12;slot<41;slot++)
  176.                     {
  177.                         if(items[slot].count == 0)
  178.                         {
  179.                             freeslot = true;
  180.                             break;                
  181.                         }      
  182.                     }
  183.                     if(freeslot) // put the unused items back into inventory
  184.                     {
  185.                         itemcount -= cost;
  186.                         items[slot].itemnum = thisevent->prizeid[prizeid];
  187.                         items[slot].itemtype = thisevent->prizetype[prizeid];
  188.                         items[slot].count = 1;  
  189.                         items[slot].lifespan = 100;
  190.                         items[slot].durability = GServer->RandNumber(25, 50);
  191.                         items[slot].stats = GServer->RandNumber(1, 299);
  192.                         BEGINPACKET( pak, 0x718 );
  193.                         ADDBYTE( pak, 1 );
  194.                         ADDBYTE    ( pak, slot);
  195.                         ADDDWORD   ( pak, GServer->BuildItemHead( items[slot] ) );
  196.                         ADDDWORD   ( pak, GServer->BuildItemData( items[slot] ) );
  197.                         client->SendPacket( &pak );  
  198.                         if (thisevent->collecttype == 12)
  199.                         {
  200.                           for(int slt=72;slt<101;slt++)
  201.                           {
  202.                             if(items[slt].count == 0 && itemcount > 0)
  203.                             {
  204.                                 if(itemcount <= 999)
  205.                                 {
  206.                                     items[slt].count = itemcount;
  207.                                     items[slt].itemtype = thisevent->collecttype;
  208.                                     items[slt].itemnum = thisevent->collectid;
  209.                                     itemcount = 0;
  210.                                     RESETPACKET( pak, 0x718 );
  211.                                     ADDBYTE( pak, 1 );
  212.                                     ADDBYTE    ( pak, slt);
  213.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  214.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  215.                                     client->SendPacket( &pak );
  216.                                     Log( MSG_INFO, "Placed items into slot %i",slt );      
  217.                                 }
  218.                                 else
  219.                                 {
  220.                                     items[slt].count = 999;
  221.                                     items[slt].itemtype = thisevent->collecttype;
  222.                                     items[slt].itemnum = thisevent->collectid;  
  223.                                     itemcount -= 999;
  224.                                     RESETPACKET( pak, 0x718 );
  225.                                     ADDBYTE( pak, 1 );
  226.                                     ADDBYTE    ( pak, slt);
  227.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  228.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  229.                                     client->SendPacket( &pak );
  230.                                     Log( MSG_INFO, "Placed items into slot %i",slt );
  231.                                 }              
  232.                             }        
  233.                           }
  234.                         }
  235.                         if (thisevent->collecttype == 10)
  236.                         {
  237.                           for(int slt=42;slt<71;slt++)
  238.                           {
  239.                             if(items[slt].count == 0 && itemcount > 0)
  240.                             {
  241.                                 if(itemcount <= 999)
  242.                                 {
  243.                                     items[slt].count = itemcount;
  244.                                     items[slt].itemtype = thisevent->collecttype;
  245.                                     items[slt].itemnum = thisevent->collectid;
  246.                                     itemcount = 0;
  247.                                     RESETPACKET( pak, 0x718 );
  248.                                     ADDBYTE( pak, 1 );
  249.                                     ADDBYTE    ( pak, slt);
  250.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  251.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  252.                                     client->SendPacket( &pak );
  253.                                     Log( MSG_INFO, "Placed items into slot %i",slt );      
  254.                                 }
  255.                                 else
  256.                                 {
  257.                                     items[slt].count = 999;
  258.                                     items[slt].itemtype = thisevent->collecttype;
  259.                                     items[slt].itemnum = thisevent->collectid;  
  260.                                     itemcount -= 999;
  261.                                     RESETPACKET( pak, 0x718 );
  262.                                     ADDBYTE( pak, 1 );
  263.                                     ADDBYTE    ( pak, slt);
  264.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  265.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  266.                                     client->SendPacket( &pak );
  267.                                     Log( MSG_INFO, "Placed items into slot %i",slt );
  268.                                 }              
  269.                             }        
  270.                           }
  271.                         }  
  272.                            
  273.                     }
  274.                     else //didn't have a free slot so put all the items back
  275.                     {
  276.                        Log( MSG_INFO, "Sorry we don't have a free slot" );
  277.                        sprintf ( buffer2, "Sorry You don't have a free slot to put the item in.");
  278.                        GServer->NPCMessage(this, buffer2, thisevent->npcname);
  279.                        if (thisevent->collecttype == 12)
  280.                        {
  281.                          for(int slt=72;slt<101;slt++)
  282.                          {
  283.                             if(items[slt].count == 0 && itemcount > 0)
  284.                             {
  285.                                 if(itemcount < 999)
  286.                                 {
  287.                                     items[slt].count = itemcount;
  288.                                     items[slt].itemtype = thisevent->collecttype;
  289.                                     items[slt].itemnum = thisevent->collectid;  
  290.                                     itemcount = 0;
  291.                                     BEGINPACKET( pak, 0x718 );
  292.                                     ADDBYTE( pak, 1 );
  293.                                     ADDBYTE    ( pak, slt);
  294.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  295.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  296.                                     client->SendPacket( &pak );        
  297.                                 }
  298.                                 else
  299.                                 {
  300.                                     items[slt].count = 999;
  301.                                     items[slt].itemtype = thisevent->collecttype;
  302.                                     items[slt].itemnum = thisevent->collectid;  
  303.                                     itemcount -= 999;
  304.                                     BEGINPACKET( pak, 0x718 );
  305.                                     ADDBYTE( pak, 1 );
  306.                                     ADDBYTE    ( pak, slt);
  307.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  308.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  309.                                     client->SendPacket( &pak );
  310.                                 }              
  311.                             }        
  312.                           }
  313.                         }  
  314.                         if (thisevent->collecttype == 10)
  315.                        {
  316.                          for(int slt=42;slt<71;slt++)
  317.                          {
  318.                             if(items[slt].count == 0 && itemcount > 0)
  319.                             {
  320.                                 if(itemcount < 999)
  321.                                 {
  322.                                     items[slt].count = itemcount;
  323.                                     items[slt].itemtype = thisevent->collecttype;
  324.                                     items[slt].itemnum = thisevent->collectid;  
  325.                                     itemcount = 0;
  326.                                     BEGINPACKET( pak, 0x718 );
  327.                                     ADDBYTE( pak, 1 );
  328.                                     ADDBYTE    ( pak, slt);
  329.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  330.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  331.                                     client->SendPacket( &pak );        
  332.                                 }
  333.                                 else
  334.                                 {
  335.                                     items[slt].count = 999;
  336.                                     items[slt].itemtype = thisevent->collecttype;
  337.                                     items[slt].itemnum = thisevent->collectid;  
  338.                                     itemcount -= 999;
  339.                                     BEGINPACKET( pak, 0x718 );
  340.                                     ADDBYTE( pak, 1 );
  341.                                     ADDBYTE    ( pak, slt);
  342.                                     ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  343.                                     ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  344.                                     client->SendPacket( &pak );
  345.                                 }              
  346.                             }        
  347.                           }
  348.                         }
  349.                     }
  350.                 }
  351.                 else
  352.                 {
  353.                     for(int slt=72;slt<101;slt++) //put the stuff back into inventory
  354.                     {
  355.                          if(items[slt].count == 0 && itemcount > 0)
  356.                          {
  357.                              if(itemcount < 999)
  358.                              {
  359.                                  items[slt].count = itemcount;
  360.                                  items[slt].itemtype = thisevent->collecttype;
  361.                                  items[slt].itemnum = thisevent->collectid;    
  362.                                  itemcount = 0;    
  363.                                  BEGINPACKET( pak, 0x718 );
  364.                                  ADDBYTE( pak, 1 );
  365.                                  ADDBYTE    ( pak, slt);
  366.                                  ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  367.                                  ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  368.                                  client->SendPacket( &pak );
  369.                              }
  370.                              else
  371.                              {
  372.                                  items[slt].count = 999;
  373.                                  items[slt].itemtype = thisevent->collecttype;
  374.                                  items[slt].itemnum = thisevent->collectid;  
  375.                                  itemcount -= 999;
  376.                                  BEGINPACKET( pak, 0x718 );
  377.                                  ADDBYTE( pak, 1 );
  378.                                  ADDBYTE    ( pak, slt);
  379.                                  ADDDWORD   ( pak, GServer->BuildItemHead( items[slt] ) );
  380.                                  ADDDWORD   ( pak, GServer->BuildItemData( items[slt] ) );
  381.                                  client->SendPacket( &pak );
  382.                                  itemcount -= 999;
  383.                              }
  384.                          }  
  385.                            
  386.                     }
  387.                    
  388.                     sprintf ( buffer2, "Sorry You don't have enough for that.");
  389.                     GServer->NPCMessage(this, buffer2, thisevent->npcname);  
  390.                 }
  391.             }
  392.         }
  393.     }
  394.     return true;    
  395. }
  396.  


open MainProcesses.cpp
find
  1.  
  2. player->CheckPlayerLevelUP( );
  3.  

after, add
  1.  
  2. player->CheckPortal( );
  3.                 player->CheckEvents( );
  4.  


Open Datatypes.h
find
  1.  
  2. // -----------------------------------------------------------------------------------------
  3. // A teleport gate object
  4. // -----------------------------------------------------------------------------------------
  5. struct CTeleGate
  6. {
  7.     unsigned short id;
  8.     fPoint dest;
  9.     unsigned char destMap;
  10. };
  11.  

after, add
  1.  
  2. //------------------------------------------------------------------------------------------
  3. // Custom events, quests and games
  4. //------------------------------------------------------------------------------------------
  5.  
  6. struct CCustomString
  7. {
  8.     char prizename[50];    
  9. };
  10.        
  11. struct CCustomEvent
  12. {
  13.     unsigned short id;
  14.     UINT eventtype;
  15.     char npcname[50];
  16.     fPoint location;
  17.     unsigned short map;
  18.     UINT active;  
  19.     UINT prizetype[10];
  20.     UINT prizeid[10];
  21.     UINT prizecost[10];
  22.     CCustomString prizename[10];
  23.     UINT collecttype;
  24.     UINT collectid;
  25.     char script1[200];
  26.     char script2[200];
  27.     char script3[200];
  28.     char script4[200];
  29.     UINT radius;
  30.     char itemname[20];
  31.     bool inuse;
  32.     UINT level;
  33. };
  34.  
  35. struct CCustomGate
  36. {
  37.   unsigned short id;
  38.   fPoint source;
  39.   unsigned short sourcemap;
  40.   fPoint dest;
  41.   unsigned short destmap;    
  42.   bool active;
  43.   unsigned short radius;
  44. };
  45.  


Open Serverfunctions.cpp
find
  1.  
  2. bool CWorldServer::SendGlobalMSG( CPlayer* thisclient, char msg[200] )
  3. {
  4.            BEGINPACKET( pak, 0x0784 );
  5.            ADDSTRING( pak, thisclient->CharInfo->charname );
  6.            ADDBYTE( pak, 0 );
  7.            ADDSTRING( pak, msg );
  8.            ADDBYTE( pak, 0 );
  9.            SendToAll(&pak);
  10.            return true;    
  11. }
  12.  

after, add

  1.  
  2. // Send a PM from a specific NPC using the blue text of the shout system. Used in custom quests
  3. bool CWorldServer::NPCMessage( CPlayer* thisclient, char msg[200], char npc[50] )
  4. {
  5.     if (npc == "")
  6.         strcpy(npc, "Event NPC");
  7.     BEGINPACKET(pak, 0x0785);
  8.     ADDSTRING  ( pak, npc );
  9.     ADDBYTE    ( pak, 0 );
  10.     ADDSTRING  ( pak, msg );
  11.     ADDBYTE    ( pak, 0 );
  12.     thisclient->client->SendPacket(&pak);
  13.     return true;
  14. }
  15.  


Open gmcmds.cpp
add the following at any convenient point

  1.  
  2. else if (strcmp(command, "prize")==0)
  3.     {
  4.          if ((tmp = strtok(NULL, " "))==NULL)return true;
  5.          {
  6.              UINT prizeid = atoi(tmp);
  7.              thisclient->PrizeExchange(thisclient, prizeid);
  8.              return true;
  9.          }
  10.     }
  11.  

remember this command needs no security access level

Here is my /reload function. This (or selected parts of it) should be used to replace the existing /reload structure in gmcmds.cpp

  1.  
  2. else if (strcmp(command, "reload")==0) // *** RELOAD CONFIG.INI ******
  3.     {
  4.          if(Config.Command_Reload > thisclient->Session->accesslevel )
  5.                         return true;
  6.          if ((tmp = strtok(NULL, " "))==NULL)return true;
  7.          if(strcmp(tmp, "config")==0)
  8.          {
  9.              LoadConfigurations( (char*)filename.c_str()  );
  10.              GServer->LoadConfig( );
  11.          }
  12.          else if(strcmp(tmp, "mobs")==0)
  13.              GServer->LoadNPCData( );
  14.          else if(strcmp(tmp, "drops")==0)
  15.              GServer->LoadPYDropsData( );
  16.          else if(strcmp(tmp, "cmd")==0)
  17.              LoadConfigurations( "commands.ini" );
  18.          else if(strcmp(tmp, "events")==0)
  19.              GServer->LoadCustomEvents( );
  20.              GServer->LoadCustomTeleGate( );
  21.          else
  22.          {
  23.              Log( MSG_INFO, "Unrecognized reload command by GM %s" , thisclient->CharInfo->charname);
  24.              return true;
  25.          }
  26.          Log( MSG_GMACTION, " %s : /reload %s" , thisclient->CharInfo->charname, tmp);
  27.          char buffer2[200];
  28.          sprintf ( buffer2, "%s data has been reloaded", tmp );
  29.          SendPM(thisclient, buffer2);
  30.             return true;
  31.     }
  32.  


If you choose to use the reload function for things other than PYDrops and my custom events/telegates then make sure you add a suitable clear command at the top of each load section in startup.cpp. All of my functions included in this release already have such clear features built in. Please use these as a template

SQL
list_customgates.zip

list_customevents.zip

These events and gates are already set up for a christmas event. A teleportal is set up to go from the back of Tryteh's shop in Zant to Santa's planetoid.
You should edit table npcdata and set the dialog for Judy to 300. This will suppress her normal speech. You can also do this for Santa if you like.

How the SQL works
customgates
id = unique identifier. This field is the primary key. Don't worry about it. MySQL will assign a number automatically.
name = Write what you like here. the server does not use this. It is just there to remind you what your telegate does.
sourcemap = map id where the custom portal goes from
sourcex and sourcey = X,Y coordinates for the exact center of the portal.
destmap, destx and desty destination map and coordinates where the character will be teleported to.
radius = the action radius around the center of the portal. The larger you set this, the larger the area in which the character will be teleported.
active = set to 1 to make this portal active. Set to 0 to disable it. Reload after making changes.

Customevents
id = unique identifier. This field is the primary key. Don't worry about it. MySQL will assign a number automatically.
eventtype = reserved for future expansion. leave at zero.
npcname = the name of the npc which is the quest giver. this value will be used in the code when the npc talks to you.
X,Y,map = the map id and coordinates. Set this to the same value as the npc location in list_npc
active = set to 1 for on and 0 for off. Reload after changes.
pc1 to pc10 = Prize Cost for each of the 10 configurable prizes. This is the cost in collect items. It is acceptable to leave some at zero if you have less than 10 prizes.
pt1 to pt10 = Prize Type. The item type of the prize. Acceptable values are 1 through 9. Do not use 10 or higher at present as the item WILL be placed into the first inventory tab and not PAT or other tabs. Later upgrades will include the ability to use other tabs.
pi1 to pi10 = Prize Item#. The item number of the prize.
pn1 to pn10 = Prize Name. Yes you have to type in the name that you want the server to display in npc dialog.
script1 = the main script that the npc will say to you when you first talk to them.
script2 = the script used by the npc to tell you that you can choose one of the available items as your prize.
script3, script4 = reserved for further expansion.
itemname = The name of the item you want the players to collect.
collecttype, collectnum = the item type and item number of the item you wish your players to collect. The item must be either type 10 or 12. the code will not work with any other type of item.
level = reserved for later expansion. Will be used to restrict certain quest based events to a minimum level. Wait for upcoming custom quests code, currently in development for further functionality.

To get a prize you need to
1) have enough collect items to be able to pay for it
2) type '/prize X' where X is the item number on the list that the npc gives you. Only items that you can afford will be displayed in the list.
3) You must be within the action radius of the event giver npc when you attempt to get your prize or nothing will happen. This is so that multiple events can be running simultaneously. A totally different set of prizes may be available at each event giver npc.

OK i think I have included all the code, certainly the major stuff anyway. Anyone attempting to integrate this code should be competent enough to figure out how to register something in a Header file if i accidentally left it out. look for errors with missing classes and stuff on compilation.

Like i said i think I got them all but i might have missed something minor.
Just ask me if you don't understand something.

enjoy :)

PS don't forget to add a monster drop (Sant lottery, item number 403, item type 12) to rudolph santa (mob number 303) Set the 'prob' to about 500 to get a realistic drop rate.
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Previous

Return to Question Zone

Who is online

Users browsing this forum: No registered users and 2 guests