Skip to content

Commit 0fc4f97

Browse files
committed
Adding python plugin callouts for various events. Will likely need to reconsider where they are to be put on the CPP side a bit more carefully.
'OnClientConnect' 'OnClientDisconnect' 'OnClientPutInServer' 'OnPlayerHurt' 'OnPlayerDeath' Already existing are 'OnPluginLoad' 'OnPluginUnload'
1 parent 0abf44e commit 0fc4f97

File tree

13 files changed

+486
-152
lines changed

13 files changed

+486
-152
lines changed

PyPlugins/TestLoadPlugin.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

PyPlugins/pyplugins.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#tests/TestImportsPlugin.py
55
#tests/TestExceptionTracebackPlugin.py
66
#tests/TestLoadAnotherFile.py
7-
tests/TestPlayerHurt.py
7+
#tests/TestPlayerHurt.py
8+
#tests/TestPlayerDeath.py
9+
tests/TestConnections.py
810
#SampleEvents.py
911
#ManyRaces/AdventureTest.py

PyPlugins/tests/TestConnections.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import Source2Py
2+
import logging, inspect
3+
import traceback
4+
5+
#logging.basicConfig(filename='SampleEvents.log', encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
6+
logging.basicConfig(filename='tests/TestConnections.log', encoding='utf-8', level=logging.DEBUG, format='[%(asctime)s]%(message)s', datefmt='%H:%M:%S')
7+
log = logging
8+
9+
10+
def alog(message: str, callername: bool = True):
11+
caller = str("")
12+
if (callername):
13+
caller = "[" + str(inspect.stack()[1].function) + "] "
14+
Source2Py.ServerPrint("[TestConnections]" + caller + str(message))
15+
log.info(msg=("[TestConnections]" + caller + str(message)))
16+
pass
17+
18+
alog("START")
19+
class TestConnections:
20+
''' note that python does not need typing in it's method declarations but here it is being used
21+
as a reminder of the incoming type from CPP.
22+
'''
23+
def OnClientConnected(self,
24+
_slot: int,
25+
_name: str,
26+
_xuid: int,
27+
_networkID: str,
28+
_ipAddress: str,
29+
_fake: bool):
30+
#first brush when player connects, no name available yet.
31+
alog("START")
32+
try:
33+
alog("slot: " + str(_slot))
34+
alog(_name + " connected")
35+
alog("xuid: " + str(_xuid))
36+
alog("networkID: " + str(_networkID))
37+
alog("ipAddress: " + str(_ipAddress))
38+
alog("fake: " + str(_fake))
39+
except Exception as e:
40+
alog(e)
41+
alog(traceback.format_exc())
42+
alog("END")
43+
pass
44+
def OnClientPutInServer(self,
45+
_slot: int,
46+
_name: str,
47+
_type: int,
48+
# type values could be:
49+
# 0 - player
50+
# 1 - fake player (bot)
51+
# 2 - unknown
52+
_xuid: int):
53+
alog("START")
54+
try:
55+
alog("slot: " + str(_slot))
56+
alog(_name + " put in server")
57+
alog("type: " + str(_type))
58+
alog("xuid: " + str(_xuid))
59+
except Exception as e:
60+
alog(e)
61+
alog(traceback.format_exc())
62+
alog("END")
63+
pass
64+
def OnClientDisconnect(self,
65+
_slot: int,
66+
_reason: int,
67+
_name: str,
68+
_xuid: int,
69+
_networkID: str):
70+
alog("START")
71+
try:
72+
alog("slot: " + str(_slot))
73+
alog("reason: " + str(_reason))
74+
alog(_name + " disconnected")
75+
alog("xuid: " + str(_xuid))
76+
alog("networkID: " + str(_networkID))
77+
except Exception as e:
78+
alog(e)
79+
alog(traceback.format_exc())
80+
alog("END")
81+
pass
82+

PyPlugins/tests/TestPlayerDeath.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import Source2Py
2+
import logging, inspect
3+
import traceback
4+
5+
#logging.basicConfig(filename='SampleEvents.log', encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
6+
logging.basicConfig(filename='tests/TestPlayerDeath.log', encoding='utf-8', level=logging.DEBUG, format='[%(asctime)s]%(message)s', datefmt='%H:%M:%S')
7+
log = logging
8+
9+
10+
def alog(message: str, callername: bool = True):
11+
caller = str("")
12+
if (callername):
13+
caller = "[" + str(inspect.stack()[1].function) + "] "
14+
Source2Py.ServerPrint("[TestPlayerDeath]" + caller + str(message))
15+
log.info(msg=("[TestPlayerDeath]" + caller + str(message)))
16+
pass
17+
18+
alog("START")
19+
20+
from tests import dumped_events
21+
22+
#base game events
23+
event_dict_of_dict = dict({})
24+
for k, v in dumped_events.dumped_events.items():
25+
event_dict_of_dict.update(v)
26+
27+
class Event(object):
28+
def __setitem__(self, key, value):
29+
setattr(self, key, value)
30+
def __getitem__(self, key):
31+
return getattr(self, key)
32+
def items(self):
33+
return self.__dict__.items()
34+
def __init__(self, _event):
35+
try:
36+
self["name"] = _event.GetName()
37+
keys = event_dict_of_dict.get(self["name"], dict())
38+
for k, v in keys.items():
39+
GEKS = Source2Py.GameEventKeySymbol_t(k)
40+
41+
# some or all may be wrong, but working for now
42+
if (v == "string"):
43+
self[k] = _event.GetString(GEKS, "None")
44+
elif (v == "bool"):
45+
self[k] = _event.GetBool(GEKS, False)
46+
elif (v == "byte"):
47+
self[k] = _event.GetInt(GEKS, -1) #python cares not, will automagically sort this mess
48+
elif (v == "short"): #mess
49+
self[k] = _event.GetInt(GEKS, -1) #mess
50+
elif (v == "long"): #mess
51+
self[k] = _event.GetInt(GEKS, -1) #mess
52+
elif (v == "int"): #mess
53+
self[k] = _event.GetInt(GEKS, -1) #mess
54+
elif (v == "float"): #mess
55+
self[k] = _event.GetFloat(GEKS, -1.0) #mess
56+
elif (v == "player_pawn"): #mess
57+
self[k] = _event.GetInt(GEKS, -1) #mess
58+
elif (v == "playercontroller"): #universally used as player id on server for all events (so far)
59+
self[k] = _event.GetPlayerSlot(GEKS).Get()
60+
#self[k] = _event.GetInt(GEKS, -1)
61+
62+
elif (v == "uint64"): #player steamid or contentid on steam network
63+
self[k] = _event.GetUint64(GEKS, 0)
64+
65+
elif (v == "strict_ehandle"):
66+
#GetEntity is used for _pawn keys like attacker_pawn and userid_pawn which are the only ones currently using strict_ehandle
67+
#self[k] = _event.GetEntity(GEKS, None)
68+
pass
69+
else: # local, hint_,
70+
alog("else!!! " + str(k) + " " + str(v))
71+
pass
72+
#alog("K: " + k + " V: " + v + ": " + str(self[k])) except Exception as e:
73+
except Exception as e:
74+
alog(e)
75+
alog(traceback.format_exc())
76+
77+
class TestPlayerDeath:
78+
'''"player_death":dict({
79+
"userid":"playercontroller",
80+
"userid_pawn":"strict_ehandle",
81+
"attacker":"playercontroller",
82+
"attacker_pawn":"strict_ehandle",
83+
"assister":"playercontroller",
84+
"assister_pawn":"strict_ehandle",
85+
"assistedflash":"bool",
86+
"weapon":"string",
87+
"weapon_itemid":"string",
88+
"weapon_fauxitemid":"string",
89+
"weapon_originalowner_xuid":"string",
90+
"headshot":"bool",
91+
"dominated":"short",
92+
"revenge":"short",
93+
"wipe":"short",
94+
"penetrated":"short",
95+
"noreplay":"bool",
96+
"noscope":"bool",
97+
"thrusmoke":"bool",
98+
"attackerblind":"bool",
99+
"distance":"float",
100+
"dmg_health":"short",
101+
"dmg_armor":"byte",
102+
"hitgroup":"byte",
103+
"attackerinair":"bool",
104+
}),'''
105+
def OnPluginLoad(self):
106+
alog("successfully loaded")
107+
pass
108+
def _heal(self, who, amount):
109+
player = Source2Py.ADVPlayer(who)
110+
player.AddHealth(amount)
111+
def _testDeath_old(self, event):
112+
geks = Source2Py.GameEventKeySymbol_t("userid")
113+
playerid = event.GetPlayerSlot(geks).Get()
114+
who_died = Source2Py.ADVPlayer(playerid)
115+
116+
geks = Source2Py.GameEventKeySymbol_t("attacker")
117+
attackerid = event.GetPlayerSlot(geks).Get()
118+
self._heal(self, attackerid, 35)
119+
120+
geks = Source2Py.GameEventKeySymbol_t("assister")
121+
assisterid = event.GetPlayerSlot(geks).Get()
122+
if (assisterid>=0):
123+
self._heal(self, attackerid, 5)
124+
125+
alog("player slot:" + str(int(playerid)) + " name:" + str(who_died.GetName()))
126+
pass
127+
def _testDeath_new(self, event):
128+
ev = Event(event)
129+
for k, v in ev.items():
130+
alog(str(k) + " | " + str(v))
131+
132+
victim = Source2Py.ADVPlayer(ev['userid'])
133+
attacker = Source2Py.ADVPlayer(ev['attacker'])
134+
assister = Source2Py.ADVPlayer(ev['assister'])
135+
136+
killstring = victim.GetName() + " was killed by "
137+
138+
if (attacker.IsValid()):
139+
killstring = killstring + attacker.GetName()
140+
heal = 15
141+
current_hp = attacker.GetHealth()
142+
alog(str(attacker.GetName() + " healed by " + str(heal) + " from " + str(current_hp) + " to " + str(current_hp+heal)))
143+
attacker.AddHealth(15)
144+
145+
if (assister.IsValid()):
146+
killstring = killstring + ", and " + assister.GetName()
147+
heal = 5
148+
current_hp = assister.GetHealth()
149+
alog(str(assister.GetName() + " healed by " + str(heal) + " from " + str(current_hp) + " to " + str(current_hp+heal)))
150+
assister.AddHealth(5)
151+
152+
alog(killstring)
153+
pass
154+
def OnPlayerDeath(self, event):
155+
alog("START")
156+
try:
157+
#self._testDeath_old(self, event)
158+
self._testDeath_new(self, event)
159+
except Exception as e:
160+
alog(e)
161+
alog(traceback.format_exc())
162+
alog("END")
163+
pass

PyPlugins/tests/TestPlayerHurt.py

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import traceback
44

55
#logging.basicConfig(filename='SampleEvents.log', encoding='utf-8', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
6-
logging.basicConfig(filename='TestPlayerHurt.log', encoding='utf-8', level=logging.DEBUG, format='[%(asctime)s]%(message)s', datefmt='%H:%M:%S')
6+
logging.basicConfig(filename='tests/TestPlayerHurt.log', encoding='utf-8', level=logging.DEBUG, format='[%(asctime)s]%(message)s', datefmt='%H:%M:%S')
77
log = logging
88

99

@@ -31,15 +31,15 @@ class TestPlayerHurt:
3131
}),'''
3232
def OnPluginLoad(self):
3333
alog("successfully loaded")
34-
#Source2Py.ServerPrint("OnLoad - TestPlayerHurt successfully loaded")
3534
pass
3635

3736
def _testGetPawnEHandle(self, event):
38-
geks = Source2Py.GameEventKeySymbol_t("attacker_pawn")
39-
peHandle = event.GetPawnEHandle(geks) #strict_ehandle??
40-
alog("peHandle type: " + str(type(peHandle)))
37+
#currently no viable route to pawn m_iHealth() that doesn't result in read access violation
38+
#geks = Source2Py.GameEventKeySymbol_t("attacker_pawn")
39+
#peHandle = event.GetPawnEHandle(geks) #strict_ehandle??
40+
#alog("peHandle type: " + str(type(peHandle)))
41+
#peHandle.TestSetHealth() #crashes for now.
4142

42-
ent = peHandle.TestHealthCEH()
4343
pass
4444
def _testGetPlayerSlot(self, event):
4545
#using GetInt("userid") or //"attacker"
@@ -67,22 +67,56 @@ def _testGetPlayerSlot(self, event):
6767
else:
6868
Source2Py.ServerPrint("aslot.TestAddHealth(" + str(heal) + ") -failed-")
6969
pass
70+
71+
def _test_ADVAPI_init(self, event, player):
72+
geks = Source2Py.GameEventKeySymbol_t(player)
73+
74+
p_int = Source2Py.ADVPlayer( event.GetPlayerSlot(geks).Get() )
75+
alog(str(player) + "int ADVPlayer.IsValid(): " + str(p_int.IsValid()))
76+
alog(str(player) + "int ADVPlayer.test(): " + str(p_int.test()))
77+
78+
#p_slot = Source2Py.ADVPlayer( event.GetPlayerSlot(geks) )
79+
#alog(str(player) + "slot ADVPlayer.IsValid(): " + str(p_slot.IsValid()))
80+
#alog(str(player) + "slot ADVPlayer.test(): " + str(p_slot.test()))
81+
def _testADVAPI(self, event):
82+
alog("_testADVAPI START")
83+
84+
self._test_ADVAPI_init(self, event, "userid")
85+
self._test_ADVAPI_init(self, event, "attacker")
86+
87+
if (False):
88+
#this stuff also works so I'll leave it here
89+
geks = Source2Py.GameEventKeySymbol_t("userid")
90+
victim = Source2Py.ADVPlayer(event.GetPlayerSlot(geks).Get())
91+
if(victim.IsValid()):
92+
alog("victim is valid")
93+
else:
94+
alog("victim is invalid")
95+
96+
geks = Source2Py.GameEventKeySymbol_t("attacker")
97+
attacker = Source2Py.ADVPlayer(event.GetPlayerSlot(geks))
98+
if(attacker.IsValid()):
99+
alog("attacker is valid")
100+
else:
101+
alog("attacker is invalid")
102+
103+
alog("test self.GetHealth() on attacker: " + str(attacker.test()))
104+
alog("_testADVAPI END")
105+
pass
70106
def OnPlayerHurt(self, event):
71107
alog("START")
72108

73109
try:
110+
#unsuccessful so far
74111
#self._testGetPawnEHandle(self, event)
75-
self._testGetPlayerSlot(self, event)
112+
113+
#succeeded, woo!
114+
#self._testGetPlayerSlot(self, event) #"life steal" / "vampirism"
115+
self._testADVAPI(self, event)
76116
except Exception as e:
77117
alog(e)
78118
alog(traceback.format_exc())
79119

80-
#aentity.TestHealth()
81-
82-
#geks = Source2Py.GameEventKeySymbol_t("userid_pawn")
83-
#vpawn = event.GetPlayerPawn(geks)
84-
#vpawn.TestHealth()
85-
86120
Source2Py.ServerPrint("OnPlayerHurt - TestPlayerHurt END")
87121
pass
88122

0 commit comments

Comments
 (0)