PlayerEntity Attributes (Cash)

Please post any questions about developing your plugin here. Please use the search function before posting!
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

PlayerEntity Attributes (Cash)

Postby Predz » Sat Oct 04, 2014 3:29 pm

If you change the player's cash. The cash attribute doesn't update when they gain cash due to round start or on player kill. The value just stays at whatever it was set at.

Extra Info: When it is set it appears as you cash in game, and can purchase weapons, etc with the cash. However the attribute in PlayerEntity does not change after setting it.

Is this a problem for just me, or everyone?
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Oct 04, 2014 3:32 pm

That doesn't sound right. We don't cache that value, we retrieve it each time it is called. Can you post reproducible code so that we can figure out what is going on?
Image
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Sat Oct 04, 2014 3:38 pm

Code: Select all

class Boots(Identifiers.ITEM):
   ## Name of the item.
   name = 'Boots of Speed'
   
   ## Category this item fits into.
   category = 'Temporary Modifiers'
   
   ## Description of the item.
   description = 'A slight boost to your current speed, removes upon death.'
   
   ## Custom cost using in game cash. ($)
   cost = 3200
   
   ## Currency (Used for purchase text)
   currency = '$'
   
   ## Define all events.
   def __init__(self):
      self.events = {'player_spawn': self.player_spawn, 'player_death': self.player_death}
      
   def player_buy(self, userid):
      player = Playerinfo(userid)
      if not self.name in player.itemlist:
         SayText2(message=str(player.ent.cash)).send()
         if player.ent.cash >= self.cost:
            player.ent.cash -= self.cost
            player.ent.speed += 0.2
            player.itemlist.append(self.name)
            return 2
         else:
            return 1
      else:
         return 0
            
   def player_spawn(self, ev):
      player = Playerinfo(ev.get_int('userid'))
      player.ent.speed += 0.2
            
   def player_death(self, ev):
      player = Playerinfo(ev.get_int('userid'))
      player.itemlist.remove(self.name)
Hedgehog
Member
Posts: 62
Joined: Sun Nov 03, 2013 8:54 pm

Postby Hedgehog » Sat Oct 04, 2014 5:05 pm

It happens only if you saved PlayerEntity.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Oct 04, 2014 5:30 pm

L'In20Cible wrote:Please, always provide your entire code (including the imports, the classes, etc.) and the content of all related files.

10 characters bleh
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Sat Oct 04, 2014 6:25 pm

satoon101 wrote:That doesn't sound right. We don't cache that value, we retrieve it each time it is called. Can you post reproducible code so that we can figure out what is going on?


Hedgehog wrote:It happens only if you saved PlayerEntity.


Thanks guys. Works perfectly fine now. Didn't realize PlayerEntity needs to be called to update all the attributes again.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Oct 04, 2014 7:30 pm

Predz wrote:Didn't realize PlayerEntity needs to be called to update all the attributes again.
False! The value is always retrieved at the time __getattr__ is called. The problem is somewhere else in your code.
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Oct 04, 2014 7:38 pm

Yeah, __getattr__ calls <Edict>.get_prop_int('m_iAccount') each and every time you retrieve the value. I would really like to see the entire reproducible code, if you don't mind.
Image
Hedgehog
Member
Posts: 62
Joined: Sun Nov 03, 2013 8:54 pm

Postby Hedgehog » Sat Oct 04, 2014 7:58 pm

Something like this:

Syntax: Select all

from players.entity import PlayerEntity

_cache = {}


class MyPlayerEntity(PlayerEntity):
def __new__(cls, userid):
index = index_from_userid(userid)

if not index:
raise ValueError('Invalid userid "%s"' % userid)

if not index in _cache:
_cache[index] = super(MyPlayerEntity, cls).__new__(cls, index)
_cache[index].drugged = None

return _cache[index]


CS:S, Sep 17 build, Linux
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Sat Oct 04, 2014 8:06 pm

Have a look at this, this has been stripped from my long python file but still replicates the error. (Would post the 1000 line file but you hate me for scruffy coding :confused:

Syntax: Select all

from players.entity import PlayerEntity
from events.manager import event_registry
from players.helpers import index_from_userid
from messages import SayText2

class Identifiers:
class CLASS:
pass
class ITEM:
pass
class SKILL:
pass
class ULTIMATE:
pass

class Boots(Identifiers.ITEM):
## Name of the item.
name = 'Boots of Speed'

## Category this item fits into.
category = 'Enhancements'

## Description of the item.
description = 'A slight boost to your current speed, removes upon death.'

## Custom cost using in game cash. ($)
cost = 3200

## Currency (Used for purchase text)
currency = '$'

def player_say(self, ev):
if ev.get_string('text') == 'test':
player = Playerinfo(ev.get_int('userid'))
if not self.name in player.itemlist:
if player.ent.cash >= self.cost:
player.ent.cash -= self.cost
player.ent.speed += 0.2
player.itemlist.append(self.name)
SayText2(message='Bought').send(index_from_userid(ev.get_int('userid')))
else:
SayText2(message='Not Enough').send(index_from_userid(ev.get_int('userid')))
else:
SayText2(message='Already Own').send(index_from_userid(ev.get_int('userid')))

def player_spawn(self, ev):
player = Playerinfo(ev.get_int('userid'))
player.ent.speed += 0.2

def player_death(self, ev):
player = Playerinfo(ev.get_int('userid'))
player.itemlist.remove(self.name)
a = Boots()

event_registry.register_for_event('player_say', a.player_say)
event_registry.register_for_event('player_spawn', a.player_spawn)
event_registry.register_for_event('player_death', a.player_death)

class _Attributes(dict):
def __getattr__(self, attr):
self[attr] = 0
return dict.__getitem__(self, attr)

class _Players(dict):
def __call__(self, attr):
if not attr in self:
self[attr] = _Attributes()

return dict.__getitem__(self, attr)
_Playerinfo = _Players()

Players = {}

def Playerinfo(userid):
if not userid in Players:
Players[userid] = _Playerinfo(userid)
Players[userid].itemlist = []
Players[userid].ent = PlayerEntity(index_from_userid(userid))
return Players[userid]


So say you had $16000. Type "test". Then buy some weapons. Then die. Then buy it again and it will take $3200 away from the $12800 you had before you bought the weapons.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Oct 04, 2014 8:15 pm

Syntax: Select all

from events import Event
from players.entity import PlayerEntity
from players.helpers import index_from_userid

_cache = {}

class MyPlayerEntity(PlayerEntity):
def __new__(cls, userid):
index = index_from_userid(userid)

if not index:
raise ValueError('Invalid userid "%s"' % userid)

if not index in _cache:
_cache[index] = super(MyPlayerEntity, cls).__new__(cls, index)
_cache[index].drugged = None

return _cache[index]

@Event
def player_spawn(game_event):
player = MyPlayerEntity(game_event.get_int('userid'))
print(player.name, player.cash)

Code: Select all

L'In20Cible 16000
Rick 1700
L'In20Cible 14300
Rick 3600
L'In20Cible 12200
Rick 3050
L'In20Cible 13700
Rick 3700
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Sat Oct 04, 2014 8:25 pm

Did you set your own cash when you did this or just use "impulse"? Because the only way I get the error is by using:

Code: Select all

PlayerEntity(<index>).cash = <value>


This will alter your cash in game, but then your cash attribute wont alter from the value set even when you obtain it again.

Syntax: Select all

## DOESNT WORK
from players.entity import PlayerEntity
from events import Event
from players.helpers import index_from_userid
from messages import SayText2

players = {}

@Event
def player_say(ev):
userid = ev.get_int('userid')
if not userid in players:
players[userid] = PlayerEntity(index_from_userid(userid))

if ev.get_string('text') == 'a':
players[userid].cash = 10000
elif ev.get_string('text') == 'b':
SayText2(message=str(players[userid].cash)).send()


If I call __getattr__ directly it update every time.

Syntax: Select all

## WORKS
from players.entity import PlayerEntity
from events import Event
from players.helpers import index_from_userid
from messages import SayText2

players = {}

@Event
def player_say(ev):
userid = ev.get_int('userid')
if not userid in players:
players[userid] = PlayerEntity(index_from_userid(userid))

if ev.get_string('text') == 'a':
players[userid].cash = 10000
elif ev.get_string('text') == 'b':
SayText2(message=str(players[userid].__getattr__('cash'))).send()
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Oct 04, 2014 9:08 pm

You are right. I was able to reproduce it and found out why this is happening. Open the file ../addons/source-python/packages/entities/entity.py and at line 228, replace the following lines:

Syntax: Select all

# Is the attribute a type description for this entity?
if attr in self.datamaps:
With the following ones:

Syntax: Select all

# Is the attribute a type description for this entity?
elif attr in self.datamaps:
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Sat Oct 04, 2014 9:23 pm

Oops, good catch. We can fix that on the master branch, but I don't believe that issue exists on the entities_changes branch. I hope to finalize changes on that branch in the next few days, and merge it with master.
Image
Predz
Senior Member
Posts: 158
Joined: Wed Aug 08, 2012 9:05 pm
Location: Bristol, United Kingdom

Postby Predz » Sun Oct 05, 2014 7:48 am

Thanks L'In2Cible. Will continue on my project now :D

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 150 guests