Post Reply 
 
Thread Rating:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
e_Carnivores - Making Carnivores hunt
Author Message
Capes
Journeyman
*

Posts: 57
Likes Given: 0
Likes Received: 1 in 1 posts
Joined: Mar 2018
Reputation: 0



Post: #1
e_Carnivores - Making Carnivores hunt
Alright - since this community has been very helpful in answering my many questions regarding how sphere works and such, I am submitting my first script. Please feel free to critique!

0.56d nightly.
Info - I noticed events in sphere_event_npcs.scp like e_Carnivores,e_Carnivores2 & e_Carnivores3 were blank, and in the corresponding sphere_monsters.scp file all the code was already there for critters to be carnivores.

This is my attempt to make animals hunt when hungry, provided that they are carnivores (if they have TEVENTS in their CHARDEF defined as e_Carnivores). This only effects animals.

1)
Global variable (placed in sphere_serv_triggers.scp under [FUNCTION f_onserver_start])

VAR.HUNGER_RATE_DECAY_TIME = 120

/////////////////////////////////////////////////////
///// VAR.HUNGER_RATE_DECAY_TIME = 120
//// (in secs)
//// 120 = every 2 mins at 20 mins per day cycle or reduced 10 times a day
//// so critter with maxfood=10 will eat once a day
/////////////////////////////////////////////////////

2)
Modified sphere_events_npc.scp [EVENTS]e_Carnivores,e_Carnivores2,e_Carnivores3 just like below

[EVENTS e_Carnivores]
// weak carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood

[EVENTS e_Carnivores2]
// normal carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood

[EVENTS e_Carnivores3]
// strong carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood

3)
Added this to the bottom of sphere_events_npc.scp

/////////////////////////////////////////////////////
//// EVENT e_Hunger
//// -our event handler for ON=@ HUNGER/KILL/DEATH
//// -only executes when (hunger_in_effect) is set on animal
//// -1)sets a new brain to animal and possible buff/debuff based on e__Carnivores TEVENTS
//// -2)resets brain to animal after killing (eating) so it doesn't hunt anymore
//// -3)cleans up mem from tags
/////////////////////////////////////////////////////
[EVENTS e_Hunger]
ON=@HUNGER //<-- triggered from f_Hunger_handler
IF !(<eval <I.TAG.hunger_in_effect>>)
return //no hunger_in_effect so quit
ENDIF
//change brain and do something special for given e_Carnivore's type
IF ((STRCMPI(<I.TEVENTS>,e_Carnivores)==0) || (STRCMPI(<I.TEVENTS>,e_Carnivores)==1)))
//we are e_Carnivores (weak), do something


ELSEIF ((STRCMPI(<I.TEVENTS>,e_Carnivores2)==0) || (STRCMPI(<I.TEVENTS>,e_Carnivores2)==1)))
//we are e_Carnivores2 (normal), do something


ELSEIF ((STRCMPI(<I.TEVENTS>,e_Carnivores3)==0) || (STRCMPI(<I.TEVENTS>,e_Carnivores3)==1)))
//we are e_Carnivores3 (strong), do something


ENDIF
//we are hungry attack something (change brain)
I.NPC = brain_berserk

ON=@KILL //<-- triggered after any kill
IF !(<eval <I.TAG.hunger_in_effect>>)
return //no hunger_in_effect so quit
ENDIF
//change back to animal brain, reset hunger lvl and restart timer
I.NPC = brain_animal
I.TAG.hunger_lvl =<eval <I.FOOD>>
I.TIMERF <eval <VAR.HUNGER_RATE_DECAY_TIME>> f_Hunger_handler

ON=@DEATH
IF !(<eval <I.TAG.hunger_in_effect>>)
return //no hunger_in_effect so quit
ENDIF
//clear hunger lvl tag & hunger in effect from mem
I.TAG.hunger_lvl =
I.TAG.hunger_in_effect =

/////////////////////////////////////////////////////
//// FUNCTION f_setNeedsFood
//// -prevents usage if not brain_animal (must be an animal)
//// -set hunger lvl & hunger in effect tags
//// -starts our hunger handler
/////////////////////////////////////////////////////
[FUNCTION f_setNeedsFood]
//only do if this is an animal
//set variable to store hunger level & set var to show hunger is in effect & start timer
IF (<NPC> == brain_animal)
TAG.hunger_lvl = <eval <FOOD>>
//prevents other scripts from triggering our events
TAG.hunger_in_effect = 1
TIMERF <eval <VAR.HUNGER_RATE_DECAY_TIME>> f_Hunger_handler
ENDIF

/////////////////////////////////////////////////////
//// FUNCTION f_Hunger_handler
//// -recursive routine
//// -reduces hunger lvl by 1 each interval
//// -stops loop and fires @HUNGER event of e_Hunger (events) above
/////////////////////////////////////////////////////
[FUNCTION f_Hunger_handler]
//reduce hunger lvl
I.TAG.hunger_lvl -= 1
//if hungry fire hunger trigger and exit otherwise run timer-func again
IF (<eval <I.TAG.hunger_lvl>> <= 0)
//trigger hunger event
I.TRIGGER @HUNGER
return
ENDIF
TIMERF <eval <VAR.HUNGER_RATE_DECAY_TIME>> f_Hunger_handler

/////////////////////////////////////////////////////


I have left room for adding other behaviors in [EVENTS e_Hunger] if desired.

Now I never know if that dam bear is gunna attack me or not!

Thanks to everyone!
Capes
(This post was last modified: 03-17-2018 10:46 PM by Capes.)
03-17-2018 10:36 PM
Find all posts by this user Like Post Quote this message in a reply
n1ghtwish
Apprentice
*

Posts: 40
Likes Given: 0
Likes Received: 27 in 8 posts
Joined: Jan 2016
Reputation: 0



Post: #2
RE: e_Carnivores - Making Carnivores hunt
Thank you for taking the time to post your first script!!!

I have not tested it but I do have a few suggestions

1) You don't need to use "I" as the default object... it works, but you can remove it and instead of "I.tag.blah = 123" you can simply do "tag.blah = 123"

2) VAR.HUNGER_RATE_DECAY_TIME = 120
Instead of storing your time in a GLOBAL variable, it is now common practice to store "setting" type variables in a DEFNAME block.

Example:

Code:
[DEFNAME hunger_settings]
// all your settings related to this system go here
HUNGER_RATE_DECAY_TIME = 120
SOME_OTHER_SETTING = 500

Then you access it later with "<DEF.HUNGER_RATE_DECAY_TIME>"

3) Do some research on adding a ZERO to TAGS, DEFS, VARS, etc...
example: <tag0.something>, <def0.something>
Might help with console error reduction Smile

4) Look into the "ISEVENT" property/function

5) "<dTAG.hunger_in_effect>" is essentially a shortcut for "<eval <I.TAG.hunger_in_effect>>", the "d" being placed in front of the TAG automatically returns said tag (or var or def or whatever) in decimal format, which is what EVAL does.

In your line "IF !(<eval <I.TAG.hunger_in_effect>>)" it is not necessarily required to evaluate the tag if you are simply checking to see if it exists.

--------------------------

Also, I appreciate your commenting on each block of the script... most don't do that and it will help others with installation and tailoring Smile

-NW
03-21-2018 03:11 AM
Find all posts by this user Like Post Quote this message in a reply
Capes
Journeyman
*

Posts: 57
Likes Given: 0
Likes Received: 1 in 1 posts
Joined: Mar 2018
Reputation: 0



Post: #3
RE: e_Carnivores - Making Carnivores hunt
Thank you n1ghtwish!
Based on your suggestions I have made some changes.
- No longer am I modifying sphere_*.scp files directly. Instead all code is gunna be in a customs folder, that will override the original sphere_*.scp files.

To make this work - create a file.scp (call it what you want), place it in a custom folder, make sure sphere_tables.scp reflects & reads the folder/file last.
Copy/paste below into that file. Restart server.

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//// EVENT OVERRIDES
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////
///// HUNGER_RATE_DECAY_TIME = 120
//// (in secs)
//// 120 = every 2 mins at 20 mins per day cycle or reduced 10 times a day
//// so critter with mxfood=10 will eat once a day
/////////////////////////////////////////////////////
[DEFNAME hunger_settings]
HUNGER_RATE_DECAY_TIME = 120

[EVENTS e_Carnivores]
// weak carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood

[EVENTS e_Carnivores2]
// normal carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood

[EVENTS e_Carnivores3]
// strong carnivores.
ON=@CREATE
EVENTS +e_Hunger
f_setNeedsFood


/////////////////////////////////////////////////////
//// EVENT e_Hunger
//// -our event handler for ON=@ HUNGER/KILL/DEATH
//// -only executes when (hunger_in_effect) is set on animal
//// -1)sets a new brain to animal and possible buff/debuff based on e__Carnivores EVENTS
//// -2)resets brain to animal after killing (eating) so it doesn't hunt anymore
//// -3)cleans up mem from tags
/////////////////////////////////////////////////////
[EVENTS e_Hunger]
ON=@HUNGER //<-- triggered from f_Hunger_handler

IF !(<dTAG0.hunger_in_effect>)
return //no hunger_in_effect so quit
ENDIF
//change brain and do something special for given e_Carnivore's type
IF (<TEVENTS> & e_Carnivores)
//we are e_Carnivores (weak), do something

ELSEIF (<TEVENTS> & e_Carnivores2)
//we are e_Carnivores2 (normal), do something

ELSEIF (<TEVENTS> & e_Carnivores3)
//we are e_Carnivores3 (strong), do something

ENDIF
//we are hungry attack something
NPC = brain_berserk

ON=@KILL //<-- triggered after any kill
IF !(<dTAG0.hunger_in_effect>)
return //no hunger_in_effect so quit
ENDIF
//change back to animal brain, reset hunger lvl and restart timer
NPC = brain_animal
TAG0.hunger_lvl =<eval <FOOD>>
TIMERF <dDEF.HUNGER_RATE_DECAY_TIME> f_Hunger_handler

ON=@DEATH
IF !(<dTAG0.hunger_in_effect>)
return //no hunger_in_effect so quit
ENDIF
//clear hunger lvl tag & hunger in effect from mem
TAG0.hunger_lvl =
TAG0.hunger_in_effect =

/////////////////////////////////////////////////////
//// FUNCTION f_setNeedsFood
//// -prevents usage if not brain_animal (must be an animal)
//// -set hunger lvl & hunger in effect tags
//// -starts our hunger handler
/////////////////////////////////////////////////////
[FUNCTION f_setNeedsFood]
//only do if this is an animal
//set variable to store hunger level & set var to show hunger is in effect & start timer
IF (<NPC> == brain_animal)
TAG0.hunger_lvl = <eval <FOOD>>
//prevents other scripts from triggering our events
TAG0.hunger_in_effect = 1
TIMERF <dDEF.HUNGER_RATE_DECAY_TIME> f_Hunger_handler
ENDIF


/////////////////////////////////////////////////////
//// FUNCTION f_Hunger_handler
//// -recusive routine
//// -reduces hunger lvl by 1 each interval
//// -stops recursing and fires @HUNGER event of e_Hunger (events) above
/////////////////////////////////////////////////////
[FUNCTION f_Hunger_handler]
//reduce hunger lvl
TAG0.hunger_lvl -= 1

//if hungry fire hunger trigger and exit otherwise run timer-func again
IF (<dTAG0.hunger_lvl> == 0)
//trigger hunger event
TRIGGER @HUNGER
return
ENDIF
TIMERF <dDEF.HUNGER_RATE_DECAY_TIME> f_Hunger_handler

/////////////////////////////////////////////////////

Thanks
Capes

PS- it was suggested that ISEVENT be used but that only works on EVENTS added in ON=@CREATE of chardef, and TEVENTS is a separate list so I was forced to use (<TEVENTS> & e_Carnivores2).
(This post was last modified: 03-31-2018 01:41 AM by Capes.)
03-25-2018 05:21 AM
Find all posts by this user Like Post Quote this message in a reply
Post Reply 


Forum Jump:


User(s) browsing this thread: 1 Guest(s)

This forum uses Lukasz Tkacz MyBB addons.