Page 4 of 4

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 5:37 pm
by PurpleYouko
AIP_REWD_031

  1. //set monster's attack target to the same as the owner
  2. AIP_REWD_031
  3.     CMap* map = GServer->MapList.Index[entity->Position->Map]   //get map
  4.     CCharacter* caller = map->GetCharInMap( entity->owner )     //get owner
  5.     if ( caller == NULL )                                       //owner not found. return
  6.         return AI_SUCCESS
  7.     if ( !caller->CurrentAction->InCombat )                     //if owner is not in combat then return
  8.         return AI_SUCCESS
  9.     entity->Position->source = caller->Position->current        //make entity run to owner's position to join the fight
  10.     CCharacter* target = map->GetCharInMap(caller->CurrentAction->targetID) //get target
  11.     if ( target == NULL )                                       //target not found. return
  12.         return AI_SUCCESS
  13.     entity->StartAction( target )                               //initiate combat with owners target. Packets contained in function call.
  14.     return AI_SUCCESS


Nice and simple.
Makes the entity attack the same target as his owner (if he has one)

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 5:40 pm
by PurpleYouko
AIP_REWD_032

  1. //Set PK Flag (btOnOff) in nZoneNo
  2. AIP_REWD_032
  3.     uint16 nZoneNo      //Byte 0
  4.     uint8 btOnOff       //Byte 2
  5.     CPacket pak     ( 0x070f )      //Start packet
  6.     pak.addUINT8    ( btOnOff )     //add PK flag value
  7.     GServer->SendToAllInMap(&pak, nZoneNo)  //send it
  8.     return AI_SUCCESS


Sets the PK flag on or off for a zone designated in nZoneNo

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 5:41 pm
by PurpleYouko
AIP_REWD_033

  1. //Zone (2) set Regeneration mode
  2. AIP_REWD_033
  3.     uint16 nZoneNo      //byte 0
  4.     uint8 nNewValue     //byte 2
  5.     if (nZoneNo == 0 )
  6.         CMap* map = GServer->MapList.Index [ entity->Position->Map ]    //get current map
  7.         if ( nNewValue = 0 )                    //set regeneration mode false
  8.             map->allowRegen = false
  9.         if ( nNewValue = 1 )                    //set regeneration mode true
  10.             map->allowRegen = true
  11.         if ( nNewValue = 2 )                    //toggle regeneration mode to opposite current value
  12.             map->allowRegen = !map->allowRegen
  13.     else
  14.         CMap* map = GServer->MapList.Index [ nZoneNo ]                  //Get specified map
  15.         if ( nNewValue = 0 )                    //set regeneration mode false
  16.             map->allowRegen = false
  17.         if ( nNewValue = 1 )                    //set regeneration mode true
  18.             map->allowRegen = true
  19.         if ( nNewValue = 2 )                    //toggle regeneration mode to opposite current value
  20.             map->allowRegen = !map->allowRegen
  21.     return AI_SUCCESS


I bet you didn't know that health regeneration could be turned on and off in specific maps did you? :D
Well it can and this AIP function is the one that sets it
Well actually you will have to modify some base code in your server most likely to enable this functionality but whatever.

So if nZoneno is zero it sets the current map in which the entity resides.

if it is a non-zero value then this number is used to specify the actual map in which we wish to set the regen value

This function is currently only ever used in _DE_ZS.AIP test file. Never by any real AIP files.
Could be used in maps where the current state of the map is controlled by events such as enemy invasion or control. For example with some clever coding, an event could be created where hordes of monsters attempt to take over a map and drive it's NPC population into hiding while they wait for players to liberate the map. While the map is under monster control the natural MP and HP regereration could be switched off.

All kinds of fun and games spring to mind.

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 6:07 pm
by PurpleYouko
AIP_REWD_034

  1. //Gives item to caller
  2. AIP_REWD_034
  3.     uint16 nItemNum         //Byte 0
  4.     uint16 nCount           //Byte 2
  5.     if ( !entity->IsMonster ( ) ) //Checking to make sure the entity is indeed a monster
  6.         return AI_SUCCESS
  7.     CMap* map = GServer->MapList.Index[entity->Position->Map]   //get map
  8.     CPlayer* caller = map->GetPlayerInMap( entity->owner)       //get owner
  9.     if ( caller == NULL )                                       //cant find owner so return
  10.         return AI_SUCCESS
  11.     if ( nItemNum == 0 )                                        //check the item. if zero then return
  12.         return AI_SUCCESS
  13.         //here we retrieve the item number and type from nItemNum using some fancy functions
  14.     uint16 itemType = Rose::Support::ParseItemCode ( nItemNum, Rose::Support::ParserOptions::ItemType )
  15.     uint16 itemNumber = Rose::Support::ParseItemCode ( nItemNum, Rose::Support::ParserOptions::ItemID )
  16.     CGameItem* monItem = GameData->Item ( itemType, itemNumber )    //create a gameitem which automatically self tests for validity (not in osrose)
  17.     if ( !monItem->isValid ( ) )                                //if the gameitem is invalid then return
  18.         return AI_SUCCESS
  19.     CItem newItem                                               //create a placeholder for the new item
  20.     monItem->Clone ( &newItem )                                 //clone the gameitem into the memory space of the placeholder
  21.     if ( !newItem.isStackable ( ) )                             //Is the item stackable?
  22.         newItem.count = 1                                       //Nope. Just one
  23.     else  
  24.         newItem.count = nCount;                                 //Yup. then set count to nCount
  25.     int thisslot = caller->AddItem( newItem )                   //Add the item to owners inventory and also return the slot id
  26.  
  27.     //Additem Failure.
  28.     if (thisslot == 0xffff)                                     //Additem failed so better fix the inventory in the client
  29.         CPacket pak     ( 0x07a7 )
  30.         pak.addUINT16   ( 0x00 )
  31.         pak.addUINT8    ( 0x03 )
  32.         pak.addUINT8    ( 0x00 )
  33.         caller->client->SendPacket(&pak)
  34.         return AI_SUCCESS
  35.  
  36.     //success.
  37.     CPacket pak     ( 0x071f )                                  //it worked so update inventory
  38.     pak.addUINT8    ( newItem.count )
  39.     pak.addUINT8    ( thisslot )
  40.     pak.addItem ( caller->items [ thisslot ] )
  41.     caller->client->SendPacket(&pak)
  42.     return AI_SUCCESS


So in this function the entity gives an item to its owner.
This code contains a bunch of special code that only exists in project 137 but hopefully the comments will let you know the intentions.
Conceptually it's pretty simple.

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 6:15 pm
by PurpleYouko
AIP_REWD_035

  1. //Set AiVAR
  2. AIP_REWD_035
  3.     uint16 nVarIDX      //Byte 0
  4.     uint32 iValue       //Byte 4
  5.     uint8 btOp          //Byte 8
  6.     if ( nVarIDX > 19 )                     //AIVar is an array of 20 (0 ~ 19). Can't address a location greater than 19
  7.         return AI_SUCCESS
  8.     int tempval = entity->AIVar[nVarIDX]    //Get the value currently stored in AIVar[nVarIDX]
  9.     switch(btOp)
  10.         case 6:                             //Add iValue to it
  11.             tempval += iValue
  12.         case 7:                             //Subtract iValue from it
  13.             tempval -= iValue
  14.             if(tempval <= 0)                //Make sure it stays >= 0
  15.                 tempval = 0
  16.         case 9:
  17.             tempval++                       //increment it
  18.         default:
  19.             return AI_SUCCESS
  20.     entity->AIVar[nVarIDX] = tempval        //Update the value
  21.     return AI_SUCCESS


Nice simple function that updates an entity's own AIVar value at the index pointed at by nVarIDX
There's nothing particularly special about AIVars like there is with ObjVars
AIVars are owned by each entity and are used to store values that are only relevant to that particular entity

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 6:22 pm
by PurpleYouko
AIP_REWD_036

  1. //Spawn nMonster at my position (has btMaster)?
  2. AIP_REWD_036
  3.     uint16 nMonster         //Byte 0
  4.     uint8 btMaster          //Byte 2
  5.     uint16 owner = 0        //initialize var
  6.     if ( btMaster == 1 )    //new monster has an owner
  7.         owner = entity->clientid    //and it's ME
  8.  
  9.     CMap* map = GServer->MapList.Index[ entity->Position->Map ] //get map
  10.     map->AddMonster( nMonster, entity->Position->current, owner, entity->Status->spawnid ); //Add the monster. This time we actually do have monster->Status->spawnid. It's the spawnid of entity
  11.    
  12.     return AI_SUCCESS


Spawns a new monster at my location and also owned by me.

Think of the big old tree monster in the Forest of Wandering and all the scarabs that it continually spawns.
Note: in this case we can set the spawnid of the summon to be the same as that of the owner. This can be useful because by interrogating the spawnid we can see at a glance exactly how many monsters it contains at any given time. Without this ability we might very well get overrun with scarabs and the server could lock up. :o

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 6:37 pm
by PurpleYouko
AIP_REWD_037

  1. //Spawn nMonster at nPos within iDistance (has btMaster)?
  2. AIP_REWD_037
  3.     uint16 nMonster     //Byte 0
  4.     uint16 nPos         //Byte 2
  5.     uint32 iDistance    //Byte 4
  6.     uint8 btMaster      //Byte 8
  7.     //nPos = 0 my pos
  8.     //nPos = 1 m_pDestCHAR pos
  9.     //nPos = 2 target pos
  10.  
  11.     UINT owner = 0                                              //initialize var
  12.     CMap* map = GServer->MapList.Index[ entity->Position->Map ] //get map
  13.     if(btMaster == 1)
  14.         owner = entity->clientid                                                    //set owner
  15.     if(nPos == 0)       //spawn monster in a circle with radius iDistance around my current position
  16.         position = Rose::Math::RandInCircle( entity->Position->current, iDistance ) //get position
  17.         map->AddMonster( nMonster, position, owner, entity->Status->spawnid )       //add the monster to my spawn
  18.     else if(nPos == 1) //spawn monster in a circle with radius iDistance around my destiny position
  19.         position = Rose::Math::RandInCircle( entity->Position->destiny, iDistance ) //get position
  20.         map->AddMonster( nMonster, position, owner, entity->Status->spawnid )       //add the monster to my spawn
  21.     else if(nPos == 2) //spawn monster in a circle with radius iDistance around my target's current position
  22.         CCharacter* target = entity->getCharTarget( )                               //get target
  23.         if(target == NULL)                                                          //no target so return
  24.             return AI_SUCCESS
  25.         position = Rose::Math::RandInCircle( target->Position->current, iDistance ) //get position
  26.         map->AddMonster( nMonster, position, owner, entity->Status->spawnid )       //add the monster to my spawn
  27.     return AI_SUCCESS


Same sort of thing as the last one except that this time we have 3 choices for spawn location
1 in a circle around the entitys current position
2 in a circle around the entitys destination position
3 in a circle around the entitys targets current position

in all cases we still add the new monster to the entitys spawnid
3 in a circle around the entitys targets position

Re: AIP Actions

PostPosted: Tue Jun 04, 2019 6:38 pm
by PurpleYouko
AIP Actions discussions.

Well that wraps it up for AIP rewards AKA Actions

Feel free to ask anything you like below.