Page 1 of 1
PlayerEntity Attributes (Cash)
Posted: Sat Oct 04, 2014 3:29 pm
by Predz
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?
Posted: Sat Oct 04, 2014 3:32 pm
by satoon101
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?
Posted: Sat Oct 04, 2014 3:38 pm
by Predz
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)
Posted: Sat Oct 04, 2014 5:05 pm
by Hedgehog
It happens only if you saved PlayerEntity.
Posted: Sat Oct 04, 2014 5:30 pm
by L'In20Cible
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
Posted: Sat Oct 04, 2014 6:25 pm
by Predz
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.
Posted: Sat Oct 04, 2014 7:30 pm
by L'In20Cible
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.
Posted: Sat Oct 04, 2014 7:38 pm
by satoon101
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.
Posted: Sat Oct 04, 2014 7:58 pm
by Hedgehog
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
Posted: Sat Oct 04, 2014 8:06 pm
by Predz
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
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.
Posted: Sat Oct 04, 2014 8:15 pm
by L'In20Cible
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
Posted: Sat Oct 04, 2014 8:25 pm
by Predz
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()
Posted: Sat Oct 04, 2014 9:08 pm
by L'In20Cible
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:
Posted: Sat Oct 04, 2014 9:23 pm
by satoon101
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.
Posted: Sun Oct 05, 2014 7:48 am
by Predz
Thanks L'In2Cible. Will continue on my project now
