11import time
22from enum import Enum
3+ import math
4+ import re
35
46class Team (Enum ):
57 eNoTeam = - 1
@@ -73,6 +75,138 @@ def bz_getLocaltime():
7375 myTime .dow = (now .tm_wday + 1 ) % 7
7476 return myTime
7577
78+ class bz_CustomMapObjectHandler ():
79+ pass
80+
81+ class bz_CustomZoneObject ():
82+ box = False
83+ radius2 = 25
84+ cX = 0
85+ cY = 0
86+ cZ = 0
87+ hh = 0
88+ hw = 0
89+ height = 5
90+ sin_val = 0
91+ cos_val = 1
92+
93+ def pointInZone (self , pos ):
94+ # Coordinates of player relative to the "fake" origin
95+ px = pos [0 ] - self .cX ;
96+ py = pos [1 ] - self .cY ;
97+ pz = pos [2 ] - self .cZ ;
98+
99+ if pos [2 ] < 0 :
100+ return False
101+ if pos [2 ] > self .height :
102+ return False
103+
104+ if self .box :
105+ # Instead of rotating the box against (0,0)
106+ # rotates the world in the opposite direction
107+ px , py = \
108+ ( px * cos_val + py * sin_val ), \
109+ (- px * sin_val + py * cos_val )
110+ # As the world is now simmetric remove the sign
111+ px = abs (px )
112+ py = abs (py )
113+
114+ # Check now it the point is within the box
115+ if px > hw :
116+ return False
117+ if py > hh :
118+ return False
119+ else :
120+ dist2 = px * px + py * py
121+
122+ if dist2 > self .radius2 :
123+ return False
124+ return True
125+
126+ def handleDefaultOptions (self , data ):
127+ # default values just in case
128+ self .radius2 = 25 # Default radius 5
129+ self .height = 5
130+ self .sin_val = 0
131+ self .cos_val = 1
132+
133+ # parse all the chunks
134+ for line in data :
135+ nubs = line .split ()
136+
137+ if len (nubs ) <= 1 :
138+ continue
139+
140+ key = nubs [0 ].upper ()
141+
142+ if key == 'BBOX' and len (nubs ) > 6 :
143+ self .box = True
144+
145+ xMin = float (nubs [1 ])
146+ xMax = float (nubs [2 ])
147+ yMin = float (nubs [3 ])
148+ yMax = float (nubs [4 ])
149+
150+ # Center of the rectangle, we can treat this as the "fake"
151+ # origin
152+ self .cX = (xMax + xMin ) / 2
153+ self .cY = (yMax + yMin ) / 2
154+
155+ self .hh = abs (yMax - yMin ) / 2
156+ self .hw = abs (xMax - xMin ) / 2
157+
158+ self .cZ = float (nubs [5 ])
159+ self .height = float (nubs [6 ]) - self .cZ
160+
161+ bz_debugMessage (0 ,
162+ 'WARNING: The "BBOX" attribute has been deprecated.' \
163+ ' Please use the `position` and `size` ' \
164+ 'attributes instead:' )
165+ bz_debugMessage (0 , ' position {f} {f} {f}'
166+ .format (self .cX , self .cY , self .cZ ))
167+ bz_debugMessage (0 , ' size {} {} {}'
168+ .format (self .hw , self .hh , self .height ))
169+ elif key == 'CYLINDER' and len (nubs ) > 5 :
170+ self .box = False
171+ # Center of the cylinder
172+ self .cX = float (nubs [1 ])
173+ self .cY = float (nubs [2 ])
174+ self .cZ = float (nubs [3 ])
175+ self .height = float (nubs [4 ]) - self .cZ
176+ self .radius = float (nubs [5 ])
177+
178+ bz_debugMessage (0 ,
179+ 'WARNING: The "CYLINDER" attribute has been ' \
180+ 'deprecated. Please use `radius` and ' \
181+ '`height` instead:' )
182+ bz_debugMessage (0 , ' position {} {} {}'
183+ .format (self .cX , self .cY , self .cZ ))
184+ bz_debugMessage (0 , ' radius {}' .format (self .radius ))
185+ bz_debugMessage (0 , ' height {}' .format (self .height ))
186+ elif (key == 'POSITION' or key == 'POS' ) and len (nubs ) > 3 :
187+ self .cX = float (nubs [1 ])
188+ self .cY = float (nubs [2 ])
189+ self .cZ = float (nubs [3 ])
190+ elif key == 'SIZE' and len (nubs ) > 3 :
191+ self .box = True
192+ # Half Width and Half Heigth
193+ self .hw = float (nubs [1 ])
194+ self .hh = float (nubs [2 ])
195+ self .height = float (nubs [3 ])
196+ elif (key == 'ROTATION' ) or (key == 'ROT' ):
197+ rotation = float (nubs [1 ])
198+ if not 0 < rotation < 360 :
199+ rotation = 0
200+ rotRad = rotation * math .pi / 180
201+ self .cos_val = math .cos (rotRad )
202+ self .sin_val = math .sin (rotRad )
203+ elif (key == 'RADIUS' ) or (key == 'RAD' ):
204+ self .box = False
205+ self .radius = float (nubs [1 ])
206+ self .radius *= self .radius
207+ elif key == 'HEIGHT' :
208+ self .height = float (nubs [1 ])
209+
76210bz_eGetPlayerSpawnPosEvent = 1
77211bz_eTickEvent = 2
78212bz_eRawChatMessageEvent = 3
@@ -81,7 +215,7 @@ def bz_getLocaltime():
81215bz_eFlagDroppedEvent = 6
82216bz_eShotFiredEvent = 7
83217bz_ePlayerDieEvent = 8
84-
218+ bz_ePlayerUpdateEvent = 9
85219
86220eGoodFlag = 0
87221eBadFlag = 1
@@ -170,12 +304,18 @@ def bzShotFiredEvent(plugin, playerID):
170304 event .playerID = playerID
171305 callEvents (event )
172306
173- def bzDiedEvent (plugin , playerID , flagKilledWith ):
307+ def bzDiedEvent (plugin ):
174308 event = bz_EventData (bz_ePlayerDieEvent )
175309 event .playerID = playerID
176310 event .flagKilledWith = flagKilledWith
177311 callEvents (event )
178312
313+ def bzUpdateEvent (plugin , playerID , pos ):
314+ event = bz_EventData (bz_ePlayerUpdateEvent )
315+ event .playerID = playerID ;
316+ event .pos = pos ;
317+ callEvents (event )
318+
179319# Command Handler
180320
181321class bz_CustomSlashCommandHandler ():
@@ -279,3 +419,31 @@ def bz_PollHelp(playerID):
279419 for k , v in customPollTypes .items ():
280420 reply = ' or /poll ' + k + ' ' + v .pollParameters
281421 bz_sendTextMessage (playerID , reply )
422+
423+
424+ customObjectMap = {}
425+
426+ def bz_registerCustomMapObject (objectName , handler ):
427+ if not objectName or not handler :
428+ return False
429+
430+ customObjectMap [objectName .upper ()] = handler ;
431+ return True
432+
433+ def bz_removeCustomMapObject (objectName ):
434+ if not objectName :
435+ return False
436+
437+ obj = objectName .upper ()
438+ if obj in customObjectMap :
439+ del customObjectMap [obj ]
440+ return True
441+
442+ def bz_CheckIfCustomMap (objectName ):
443+ return objectName in customObjectMap
444+
445+ def bz_customZoneMapObject (customObject , customLines ):
446+ customObjectMap [customObject ].MapObject (customObject , customLines );
447+
448+ def bz_tokenize (line ):
449+ return re .findall (r'[^"\s]\S*|".+?"' , line )
0 commit comments