Timed player regeneration

Please post any questions about developing your plugin here. Please use the search function before posting!
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Timed player regeneration

Postby arawra » Tue Dec 30, 2014 11:50 pm

I'm trying to develop a way such that certain players regenerate health periodically. The time and amount of health varies by player. This is my first solution, and was wondering if anyone had a better idea.

Syntax: Select all

def regenLoop(tick=0):
for players in PlayerGenerator():
myPlayer = playerDictionary[players]
if myPlayer['regen'] > 0:
if tick >= myPlayer['regentime'] and tick % myPlayer['regentime'] == 0:
PlayerEntity(index_from_playerinfo(players)).health += myPlayer['regen']
regenTimer = TickRepeat(regenLoop, tick+1)
regenTimer.start(1,1)
regenLoop()
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Wed Dec 31, 2014 12:09 am

I'm not sure the criteria for your regen, but maybe the following will give you an idea:

Syntax: Select all

from listeners.tick import TickRepeat
from players.entity import PlayerEntity
from players.helpers import index_from_userid


class PlayerDictionary(dict):
def __missing__(self, userid):
value = self[userid] = Player(userid)

def __delitem__(self, userid):
if userid in self:
self[userid].repeat.stop()

def clear(self):
for userid in list(self):
del self[userid]


class Player(PlayerEntity):
def __new__(cls, userid):
self = super(Player, cls).__new__(cls, index_from_userid(userid))
return self

def __init__(self, userid):
self._repeat = TickRepeat(self.regen_loop)

@property
def repeat(self):
return self._repeat

def regen_loop(self):
...


If you would be more specific as to when players are supposed to start regen'ing, the max health to regen to, the max time to regen, the max health to regen per regen cycle, etc..., we could help you further.

For the example above, you might want to look at some of the properties of a TickRepeat instance (specifically count):
http://wiki.sourcepython.com/pages/listeners.tick#TickRepeat

Also, don't forget that using 0 for the limit argument in TickRepeat.start causes the repeat to be infinite and only stop when explicitly stopped.
Image
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Postby arawra » Wed Dec 31, 2014 12:18 am

If you would like to see exactly what I have (with a class and dictionary you largely developed :wink: ) here ya go.

myPlayer.regen is the amount of health to regenerate.
myPlayer.regentime is the delay in seconds between regeneration.

If a player has a myPlayer.regen amount, you can assume they should always be regenerating.

Syntax: Select all

def heal(player, amount):
# player is a PlayerEntity/dndPlayer object
player.health += amount
if player.health > player.maxhp:
player.health = player.maxhp

def regenLoop(tick=0):
for players in PlayerGenerator():
myPlayer = dndPlayerDictionary[userid_from_playerinfo(players)]
if myPlayer.regen > 0:
if tick >= myPlayer.regentime and tick % myPlayer.regentime == 0:
heal(myPlayer, myPlayer.regen)
regenTimer = TickRepeat(regenLoop, tick+1)
regenTimer.start(1,1)
regenLoop()


I'm unfamiliar with the '@property' decorator.
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Postby arawra » Wed Dec 31, 2014 12:35 am

Here is my second solution after looking at the wiki.

Syntax: Select all

def heal(player, amount):
# player is a PlayerEntity/dndPlayer object
player.health += amount
if player.health > player.maxhp:
player.health = player.maxhp

def regenLoop():
for players in PlayerGenerator():
myPlayer = dndPlayerDictionary[userid_from_playerinfo(players)]
if not myPlayer.isdead:
if myPlayer.regen > 0:
if regenTimer.count >= myPlayer.regentime and regenTimer.count % myPlayer.regentime == 0:
heal(myPlayer, myPlayer.regen)

regenTimer = TickRepeat(regenLoop)
regenTimer.start(1,0)
arawra
Senior Member
Posts: 190
Joined: Fri Jun 21, 2013 6:51 am

Postby arawra » Thu Jan 01, 2015 6:52 pm

I got around to realizing that sometimes players may have more than one type of regeneration, and we probably should only be handling one a

Syntax: Select all

def heal(player, amount):
# player is a PlayerEntity/dndPlayer object
player.health += amount
if player.health > player.maxhp:
player.health = player.maxhp

def regenLoop():
for players in PlayerGenerator():
myPlayer = dndPlayerDictionary[userid_from_playerinfo(players)]
if not myPlayer.isdead:
regen = myPlayer.regen
remove = []
if len(regen) > 0:
for item in regen:
if len(regen) == 3:
if regen[item][2] > 0:
if regenTimer.count >= regen[item][1] and regenTimer.count % regen[item][1] == 0:
heal(myPlayer, regen[item][0])
myPlayer.regen[item][2] -= 1
else:
remove.append(myPlayer.regen[item])
else:
if regenTimer.count >= regen[item][1] and regenTimer.count % regen[item][1] == 0:
heal(myPlayer, regen[item][0])
for item in remove:
myPlayer.regen.pop(item)

@Event
def player_spawn(game_event):
spawnee_userid = game_event.get_int('userid')
spawnee = dndPlayerDictionary[spawnee_userid]

#This just sets all attributes of PlayerEntity() to their default value, i.e. max health is 100 and speed is 100%
spawnee.reset()

if spawnee.someAttribute = True:

#Player should regenerate 1 health every 4 seconds
spawnee.regen.append([1,4])

#Player should regenerate 5 health every 3 seconds, but only for 3 intervals
spawnee.regen.append([5,3,3])
User avatar
Mahi
Senior Member
Posts: 236
Joined: Wed Aug 29, 2012 8:39 pm
Location: Finland

Postby Mahi » Fri Jan 02, 2015 10:06 am

satoon101 wrote:

Syntax: Select all

class Player(PlayerEntity):
def __new__(cls, userid):
self = super(Player, cls).__new__(cls, index_from_userid(userid))
return self

def __init__(self, userid):
self._repeat = TickRepeat(self.regen_loop)

@property
def repeat(self):
return self._repeat

def regen_loop(self):
...

Is there a reason (in this case) you'd want to use __new__ instead of just calling super's __init__ in Player's __init__?
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Fri Jan 02, 2015 12:43 pm

Yes, PlayerEntity (or really BaseEntity) does a lot of stuff in __new__ but requires an index. If we don't override __new__ and call its super class' __new__ the userid would be passed instead, which would cause numerous issues.
Image

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 55 guests