· 6 years ago · Aug 07, 2019, 06:16 AM
1/*
2 make OnEquipped and OnUnequipped for non-custom weapons?
3 make hooked functions use tables? (like VSLib)
4 use multiple timers to reduce long hangs?
5 add response rule library?
6*/
7
8/*options
9fire custom weapon while restricted (default is off)
10print debug info (default is on)
11*/
12
13
14enum Keys {
15 ATTACK = 1
16 JUMP = 2
17 CROUCH = 4
18 FORWARD = 8
19 BACKWARD = 16
20 USE = 32
21 LEFT = 512
22 RIGHT = 1024
23 ATTACK2 = 2048
24 RELOAD = 8192
25 ALT1 = 16384
26 ALT2 = 32768
27 SHOWSCORES = 65536
28 SPEED = 131072
29 WALK = 262144
30 ZOOM = 524288
31 GRENADE1 = 8388608
32 GRENADE2 = 16777216
33 LOOKSPIN = 33554432
34}
35
36enum VariableTypes {
37 INTEGER = "integer"
38 FLOAT = "float"
39 BOOLEAN = "bool"
40 STRING = "string"
41 TABLE = "table"
42 ARRAY = "array"
43 FUNCTION = "function"
44 CLASS = "class"
45 INSTANCE = "instance"
46 THREAD = "thread"
47 NULL = "null"
48}
49
50const CHAR_SPACE = 32
51const CHAR_NEWLINE = 10
52
53const PRINT_START = "Hook Controller: "
54
55class PlayerInfo {
56 entity = null
57 disabled = false
58 disabledLast = false
59 heldButtonsMask = 0
60
61 lastWeapon = null
62 lastWeapons = []
63
64 constructor(ent){
65 entity = ent
66 }
67
68 function SetDisabled(isDisabled){
69 disabledLast = disabled
70 disabled = isDisabled
71 }
72
73 function IsDisabled(){
74 return disabled
75 }
76
77 function WasDisabled(){
78 return disabledLast
79 }
80
81
82 function GetEntity(){
83 return entity
84 }
85
86
87 function GetHeldButtonsMask(){
88 return heldButtonsMask
89 }
90
91 function SetHeldButtonsMask(mask){
92 heldButtonsMask = mask
93 }
94
95
96 function GetLastWeapon(){
97 return lastWeapon
98 }
99
100
101 function SetLastWeapon(ent){
102 lastWeapon = ent
103 }
104
105 function GetLastWeaponsArray(){
106 return lastWeapons
107 }
108 function SetLastWeaponsArray(array){
109 lastWeapons = array
110 }
111}
112
113class CustomWeapon {
114 viewmodel = null
115 worldmodel = null
116 scope = null
117
118 constructor(vmodel, wmodel, scriptscope){
119 viewmodel = vmodel
120 worldmodel = wmodel
121 scope = scriptscope
122 }
123
124 function GetViewmodel(){
125 return viewmodel
126 }
127
128 function GetWorldModel(){
129 return worldmodel
130 }
131
132 function GetScope(){
133 return scope
134 }
135}
136
137class EntityCreateListener {
138 oldEntities = []
139 scope = null
140 classname = null
141
142 constructor(className, scriptscope){
143 classname = className
144 scope = scriptscope
145 }
146
147 function GetClassname(){
148 return classname
149 }
150
151 function GetScope(){
152 return scope
153 }
154
155 function GetOldEntities(){
156 return oldEntities
157 }
158 function SetOldEntities(array){
159 oldEntities = array
160 }
161}
162
163class EntityMoveListener {
164 lastPosition = null
165 entity = null
166 scope = null
167
168 constructor(ent, scriptScope){
169 entity = ent
170 scope = scriptScope
171 lastPosition = entity.GetOrigin()
172 }
173
174 function GetScope(){
175 return scope
176 }
177
178 function GetEntity(){
179 return entity
180 }
181
182 function GetLastPosition(){
183 return lastPosition
184 }
185
186 function SetLastPosition(position){
187 lastPosition = position
188 }
189}
190
191class ThrowableExplodeListener {
192 scope = null
193
194 constructor(scope){
195 this.scope = scope
196 }
197
198 function GetScope(){
199 return scope
200 }
201}
202
203class Task {
204 functionKey = null
205 args = null
206 endTime = null
207
208 /*
209 We place the function in a table with the arguments so that the function can access the arguments
210 */
211 constructor(func, arguments, time){
212 functionKey = UniqueString("TaskFunction")
213 args = arguments
214 args[functionKey] <- func
215 endTime = time
216 }
217
218 function CallFunction(){
219 args[functionKey]()
220 }
221
222 function ReachedTime(){
223 return Time() >= endTime
224 }
225}
226
227class Timer {
228 constructor(hudField, time, callFunction, countDown, formatTime){
229 this.hudField = hudField
230 this.time = time
231 this.callFunction = callFunction
232 this.countDown = countDown
233 this.formatTime = formatTime
234
235 start = Time()
236 }
237
238 function FormatTime(time){
239 local seconds = ceil(time) % 60
240 local minutes = floor(ceil(time) / 60)
241 if(seconds < 10){
242 return minutes.tointeger() + ":0" + seconds.tointeger()
243 } else {
244 return minutes.tointeger() + ":" + seconds.tointeger()
245 }
246 }
247
248 function Update(){
249 local timeRemaining = -1
250
251 if(countDown){
252 timeRemaining = time - (Time() - start)
253 } else {
254 timeRemaining = Time() - start
255 }
256
257 if(formatTime){
258 hudField.dataval = FormatTime(timeRemaining)
259 } else {
260 if(countDown){
261 timeRemaining = ceil(timeRemaining).tointeger()
262 } else {
263 timeRemaining = floor(timeRemaining).tointeger()
264 }
265 hudField.dataval = timeRemaining
266 }
267
268 return (countDown && timeRemaining <= 0) || (!countDown && timeRemaining >= time)
269 }
270
271 function CallFunction(){
272 callFunction()
273 }
274
275 function GetHudField(){
276 return hudField
277 }
278
279 hudField = null
280 start = -1
281 time = -1
282 callFunction = null
283 countDown = true
284 formatTime = false
285}
286
287class ChatCommand {
288 inputCommand = false
289 commandString = null
290 commandFunction = null
291
292 constructor(command, func, isInput){
293 commandString = command
294 commandFunction = func
295 inputCommand = isInput
296 }
297
298 function CallFunction(ent, input = null){
299 if(inputCommand){
300 commandFunction(ent, input)
301 } else {
302 commandFunction(ent)
303 }
304 }
305
306 function GetCommand(){
307 return commandString
308 }
309
310 function IsInputCommand(){
311 return inputCommand
312 }
313}
314
315class ConvarListener {
316 convar = null
317 type = null
318 lastValue = null
319 scope = null
320
321 /*
322 type should be either "string" or "float"
323 */
324 constructor(convar, type, scope){
325 this.convar = convar
326 this.type = type
327 this.scope = scope
328 }
329
330 function GetScope(){
331 return scope
332 }
333
334 function GetConvar(){
335 return convar
336 }
337
338 function GetCurrentValue(){
339 if(type == "string"){
340 return Convars.GetStr(convar)
341 } else if(type == "float"){
342 return Convars.GetFloat(convar)
343 }
344 }
345
346 function GetLastValue(){
347 return lastValue
348 }
349
350 function SetLastValue(){
351 if(type == "string"){
352 lastValue = Convars.GetStr(convar)
353 } else if(type == "float"){
354 lastValue = Convars.GetFloat(convar)
355 }
356 }
357}
358
359class FunctionListener {
360 checkFunctionTable = null
361 checkFunctionKey = null
362 callFunction = null
363 singleUse = false
364
365 constructor(checkFunction, callFunction, args, singleUse){
366 checkFunctionTable = args
367 checkFunctionKey = UniqueString()
368 checkFunctionTable[checkFunctionKey] <- checkFunction
369 this.callFunction = callFunction
370 this.singleUse = singleUse
371 }
372
373 function CheckValue(){
374 if(checkFunctionTable[checkFunctionKey]()){
375 callFunction()
376 return true
377 }
378 return false
379 }
380
381 function IsSingleUse(){
382 return singleUse
383 }
384}
385
386class LockedEntity {
387 entity = null
388 angles = null
389 origin = null
390
391 constructor(entity, angles, origin){
392 this.entity = entity
393 this.angles = angles
394 this.origin = origin
395 }
396
397 function DoLock(){
398 entity.SetAngles(angles)
399 entity.SetOrigin(origin)
400 }
401}
402
403class ThrownGrenade {
404 entity = null
405 thrower = null
406 startPosition = null
407 lastPosition = null
408 lastVelocity = null
409
410 constructor(entity, thrower, startPosition, lastPosition, lastVelocity){
411 this.entity = entity
412 this.thrower = thrower
413 this.startPosition = startPosition
414 this.lastPosition = lastPosition
415 this.lastVelocity = lastVelocity
416 }
417
418 function CheckRemoved(){
419 return entity == null || !entity.IsValid()
420 }
421
422 function GetStartPosition(){
423 return startPosition
424 }
425
426 function SetLastPosition(){
427 this.lastPosition = entity.GetOrigin()
428 }
429
430 function GetLastPosition(){
431 return lastPosition
432 }
433
434 function SetLastVelocity(){
435 this.lastVelocity = entity.GetVelocity()
436 }
437
438 function GetLastVelocity(){
439 return lastVelocity
440 }
441
442 function GetThrower(){
443 return thrower
444 }
445
446 function GetEntity(){
447 return entity
448 }
449}
450
451printl("Hook Controller loaded. (Made by Daroot Leafstorm)")
452
453// options
454local debugPrint = true
455
456local customWeapons = []
457local hookScripts = []
458local tickScripts = []
459local tickFunctions = []
460local entityMoveListeners = []
461local entityCreateListeners = []
462local bileExplodeListeners = []
463local molotovExplodeListeners = []
464local convarListeners = []
465local functionListeners = []
466local chatCommands = []
467local timers = []
468local tasks = []
469local lockedEntities = []
470
471local bileJars = []
472local molotovs = []
473
474local players = []
475
476local timescaleEnt = SpawnEntityFromTable("func_timescale", {})
477
478local improvedMethods = false
479
480
481// This initializes the timer responsible for the calls to the Think function
482local timer = SpawnEntityFromTable("logic_timer",{RefireTime = 0.01})
483timer.ValidateScriptScope()
484timer.GetScriptScope()["scope"] <- this
485timer.GetScriptScope()["func"] <- function(){
486 scope.Think()
487}
488timer.ConnectOutput("OnTimer", "func")
489EntFire("!self","Enable",null,0,timer)
490
491/**
492 * Prints a message to the console with PRINT_START prepended
493 */
494local function PrintInfo(message){
495 if(debugPrint){
496 printl(PRINT_START + message)
497 }
498}
499
500/**
501 * Prints an error to the console with PRINT_START prepended
502 */
503local function PrintError(message){
504 print("\n" + PRINT_START)
505 error(message + "\n\n")
506}
507
508/**
509 * Prints an error to the console including caller, source file, variable type, and expected type with PRINT_START prepended
510 */
511local function PrintInvalidVarType(message, parameterName, expectedType, actualType){
512 local infos = getstackinfos(3)
513 PrintError(message + "\n\n\tParameter \"" + parameterName + "\" has an invalid type '" + actualType + "' ; expected: '" + expectedType + "'\n\n\tCALL\n\t\tFUNCTION: " + infos.func + "\n\t\tSOURCE: " + infos.src + "\n\t\tLINE: " + infos.line)
514}
515
516
517/**
518 * Checks the type of var, returns true if type matches, false otherwise
519 */
520local function CheckType(var, type){
521 return typeof(var) == type
522}
523
524/**
525 * Returns an array of all survivors, dead or alive
526 */
527local function GetSurvivors(){
528 local array = []
529 local ent = null
530 while (ent = Entities.FindByClassname(ent, "player")){
531 if(ent.IsValid() && ent.IsSurvivor()){
532 array.append(ent)
533 }
534 }
535
536 return array
537}
538
539/**
540 * Returns the PlayerInfo instance corresponding to the given entity if it exists, otherwise returns null
541 */
542local function FindPlayerObject(entity){
543 foreach(player in players){
544 if(player.GetEntity() == entity){
545 return player
546 }
547 }
548}
549
550/**
551 * Returns the CustomWeapon instance corresponding to the given viewmodel if it exists, otherwise returns null
552 */
553local function FindCustomWeapon(viewmodel){
554 foreach(weapon in customWeapons){
555 if(weapon.GetViewmodel().tolower() == viewmodel.tolower()){
556 return weapon
557 }
558 }
559}
560
561/**
562 * Calls a specified function by name in the provided scope with optional parameters
563 * If the function has entity or ent, it will pass the ent parameter to it
564 * If the function has player, it will pass the player parameter to it
565 */
566local function CallFunction(scope, funcName, ent = null, player = null){ // if parameters has entity (or ent), pass ent, if has player, pass player
567 if(scope != null && funcName in scope && typeof(scope[funcName]) == "function"){
568 local params = scope[funcName].getinfos().parameters
569 local index_offset = 0 // sometimes it contains "this" sometimes it doesn't?
570 if(params.find("this") != null){
571 index_offset = -1
572 }
573 if(params.find("player") != null){
574 if(params.find("ent") != null){
575 if(params.find("ent") + index_offset == 0){
576 scope[funcName](ent, player)
577 } else {
578 scope[funcName](player, ent)
579 }
580 } else if(params.find("entity") != null) {
581 if(params.find("entity") + index_offset == 0){
582 scope[funcName](ent, player)
583 } else {
584 scope[funcName](player, ent)
585 }
586 } else {
587 scope[funcName](player)
588 }
589 } else if(params.find("ent") != null || params.find("entity") != null){
590 scope[funcName](ent)
591 } else {
592 scope[funcName]()
593 }
594 }
595}
596
597/**
598 * Calls the OnInventoryChange function in the specified scope with the ent, droppedWeapons, and newWeapons parameters
599 */
600local function CallInventoryChangeFunction(scope, ent, droppedWeapons, newWeapons){
601 if(scope != null && "OnInventoryChange" in scope && CheckType(scope["OnInventoryChange"], VariableTypes.FUNCTION)){
602 scope["OnInventoryChange"](ent, droppedWeapons, newWeapons)
603 }
604}
605
606/**
607 * Calls the OnKeyPressStart_, OnKeyPressTick_, and OnKeyPressEnd_ for the specified keyName within the specified scope
608 */
609local function CallKeyPressFunctions(player, scope, keyId, keyName){
610 if(player.GetEntity().GetButtonMask() & keyId){
611 if(player.GetHeldButtonsMask() & keyId){
612 foreach(script in hookScripts){
613 CallFunction(script, "OnKeyPressTick_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
614 }
615 CallFunction(scope, "OnKeyPressTick_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
616 } else {
617 player.SetHeldButtonsMask(player.GetHeldButtonsMask() | keyId)
618 foreach(script in hookScripts){
619 CallFunction(script, "OnKeyPressStart_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
620 }
621 CallFunction(scope, "OnKeyPressStart_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
622 }
623 } else if(player.GetHeldButtonsMask() & keyId){
624 player.SetHeldButtonsMask(player.GetHeldButtonsMask() & ~keyId)
625 foreach(script in hookScripts){
626 CallFunction(script, "OnKeyPressEnd_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
627 }
628 CallFunction(scope, "OnKeyPressEnd_" + keyName, player.GetEntity().GetActiveWeapon(), player.GetEntity())
629 }
630}
631
632/**
633 * Calls OnEquipped or OnUnequipped in the custom weapon scope specified by the weaponModel parameter
634 */
635local function CallWeaponEquipFunctions(player, weaponModel){
636 if(player.GetLastWeapon() != null && NetProps.GetPropString(player.GetLastWeapon(), "m_ModelName") != weaponModel){ //we changed weapons!
637 foreach(weapon in customWeapons){
638 if(NetProps.GetPropString(player.GetLastWeapon(), "m_ModelName") == weapon.GetViewmodel()){
639 CallFunction(weapon.GetScope(),"OnUnequipped",player.GetLastWeapon(),player.GetEntity())
640 } else if(weaponModel == weapon.GetViewmodel()){
641 CallFunction(weapon.GetScope(),"OnEquipped",player.GetLastWeapon(),player.GetEntity())
642 }
643 }
644 }
645}
646
647/**
648 * Calls OnConvarChange_ in the specified scope with previousValue and newValue
649 */
650local function CallConvarChangeFunction(scope, convar, previousValue, newValue){
651 local funcName = "OnConvarChange_" + convar
652 if(scope != null && funcName in scope && CheckType(scope[funcName], VariableTypes.FUNCTION)){
653 scope[funcName](previousValue, newValue)
654 }
655}
656
657PrintInfo("HookController initialized at " + Time() + "\n\ttimer: " + timer)
658
659/**
660 * Called every tick, handles tasks, hooks, etc
661 */
662function Think(){
663 if((improvedMethods && Time() > 0.034) || !improvedMethods){
664 foreach(script in hookScripts){
665 CallFunction(script, "OnTick")
666 }
667 foreach(script in tickScripts){
668 CallFunction(script, "OnTick")
669 }
670 foreach(func in tickFunctions){
671 func()
672 }
673 foreach(weapon in customWeapons){
674 CallFunction(weapon.GetScope(), "OnTick")
675 }
676 foreach(survivor in GetSurvivors()){
677 if(players.len() == 0){
678 players.append(PlayerInfo(survivor))
679 } else {
680 local found = false
681 for(local i=0; i<players.len();i++){
682 local player = players[i]
683 if(player.GetEntity() != null && player.GetEntity().IsValid()){
684 if(survivor.GetPlayerUserId() == player.GetEntity().GetPlayerUserId()){
685 found = true
686 }
687
688 if((NetProps.GetPropEntity(survivor, "m_tongueOwner") && (NetProps.GetPropInt(survivor, "m_isHangingFromTongue") || NetProps.GetPropInt(survivor, "m_reachedTongueOwner") || Time() >= NetProps.GetPropFloat(survivor, "m_tongueVictimTimer") + 1)) || NetProps.GetPropEntity(survivor, "m_jockeyAttacker") || NetProps.GetPropEntity(survivor, "m_pounceAttacker") || (NetProps.GetPropEntity(survivor, "m_pummelAttacker") || NetProps.GetPropEntity(survivor, "m_carryAttacker"))){
689 player.SetDisabled(true)
690 } else {
691 player.SetDisabled(false)
692 }
693
694 if(player.WasDisabled() && !player.IsDisabled()){
695 foreach(weapon in customWeapons){
696 CallFunction(weapon.GetScope(), "OnReleased", player.GetEntity().GetActiveWeapon(), player.GetEntity())
697 }
698 }
699 if(!player.WasDisabled() && player.IsDisabled()){
700 foreach(weapon in customWeapons){
701 CallFunction(weapon.GetScope(), "OnRestricted", player.GetEntity().GetActiveWeapon(), player.GetEntity())
702 }
703 }
704 } else {
705 players.remove(i)
706 i -= 1
707 }
708 }
709 if(!found){
710 players.append(PlayerInfo(survivor))
711 }
712 }
713 }
714
715 if(bileExplodeListeners.len() > 0){
716 for(local i = 0; i < bileJars.len(); i++){
717 local bileJar = bileJars[i]
718 if(bileJar.CheckRemoved()){
719 foreach(listener in bileExplodeListeners){
720 if("OnBileExplode" in listener.GetScope() && CheckType(listener.GetScope()["OnBileExplode"], VariableTypes.FUNCTION)){
721 listener.GetScope()["OnBileExplode"](bileJar.GetThrower(), bileJar.GetStartPosition(), bileJar.GetLastPosition())
722 }
723 }
724 bileJars.remove(i)
725 i--
726 } else {
727 bileJar.SetLastPosition()
728 bileJar.SetLastVelocity()
729 }
730 }
731
732 local newBileJar = null
733 while(newBileJar = Entities.FindByClassname(newBileJar, "vomitjar_projectile")){
734 local foundInstance = false
735 foreach(bileJar in bileJars){
736 if(bileJar.GetEntity() == newBileJar){
737 foundInstance = true
738 }
739 }
740 if(!foundInstance){
741 bileJars.append(ThrownGrenade(newBileJar, NetProps.GetPropEntity(newBileJar, "m_hThrower"), newBileJar.GetOrigin(), newBileJar.GetOrigin(), newBileJar.GetVelocity()))
742 }
743 }
744 }
745
746 if(molotovExplodeListeners.len() > 0){
747 for(local i = 0; i < molotovs.len(); i++){
748 local molotov = molotovs[i]
749 if(molotov.CheckRemoved()){
750 foreach(listener in molotovExplodeListeners){
751 if("OnMolotovExplode" in listener.GetScope() && CheckType(listener.GetScope()["OnMolotovExplode"], VariableTypes.FUNCTION)){
752 listener.GetScope()["OnMolotovExplode"](molotov.GetThrower(), molotov.GetStartPosition(), molotov.GetLastPosition())
753 }
754 }
755 molotovs.remove(i)
756 i--
757 } else {
758 molotov.SetLastPosition()
759 molotov.SetLastVelocity()
760 }
761 }
762
763 local newMolotov = null
764 while(newMolotov = Entities.FindByClassname(newMolotov, "molotov_projectile")){
765 local foundInstance = false
766 foreach(molotov in molotovs){
767 if(molotov.GetEntity() == newMolotov){
768 foundInstance = true
769 }
770 }
771 if(!foundInstance){
772 molotovs.append(ThrownGrenade(newMolotov, NetProps.GetPropEntity(newMolotov, "m_hThrower"), newMolotov.GetOrigin(), newMolotov.GetOrigin(), newMolotov.GetVelocity()))
773 }
774 }
775 }
776
777 for(local i=0; i < timers.len(); i++){
778 if(timers[i].Update()){
779 local timer = timers[i]
780 timer.CallFunction()
781 for(local j = 0; j < timers.len(); j++){
782 if(timer.GetHudField() == timers[i].GetHudField()){
783 timers.remove(j)
784 i--
785 break
786 }
787 }
788 }
789 }
790
791 for(local i=0; i < functionListeners.len(); i+=1){
792 if(functionListeners[i].CheckValue() && functionListeners[i].IsSingleUse()){
793 functionListeners.remove(i)
794 i -= 1
795 }
796 }
797
798 foreach(lockedEntity in lockedEntities){
799 lockedEntity.DoLock()
800 }
801
802 foreach(listener in entityMoveListeners){
803 local currentPosition = listener.GetEntity().GetOrigin()
804 local oldPosition = listener.GetLastPosition()
805 if(oldPosition != null && currentPosition != oldPosition){
806 CallFunction(listener.GetScope(),"OnEntityMove",listener.GetEntity())
807 }
808 listener.SetLastPosition(listener.GetEntity().GetOrigin())
809 }
810
811 foreach(listener in entityCreateListeners){
812 local ent = null
813 local entityArray = []
814 while((ent = Entities.FindByClassname(ent,listener.GetClassname())) != null){
815 entityArray.append(ent)
816 }
817 if(listener.GetOldEntities() != null && listener.GetOldEntities().len() < entityArray.len()){ // this may miss entities if an entity of the same type is killed at the same time as one is spawned
818 entityArray.sort(@(a, b) a.GetEntityIndex() <=> b.GetEntityIndex())
819 local newEntities = entityArray.slice(listener.GetOldEntities().len())
820 foreach(newEntity in newEntities){
821 CallFunction(listener.GetScope(), "OnEntCreate_" + listener.GetClassname(), newEntity)
822 }
823 }
824 listener.SetOldEntities(entityArray)
825 }
826
827 foreach(listener in convarListeners){
828 if(listener.GetCurrentValue() != listener.GetLastValue){
829 CallConvarChangeFunction(listener.GetScope(), listener.GetConvar(), listener.GetLastValue(), listener.GetCurrentValue())
830 }
831
832 listener.SetLastValue()
833 }
834
835 if(customWeapons.len() > 0 || hookScripts.len() > 0){
836 foreach(player in players){
837 if(player.GetEntity() == null || !player.GetEntity().IsValid() || player.GetEntity().IsDead()){
838 player.SetDisabled(true)
839 } else {
840 local weaponModel = NetProps.GetPropString(player.GetEntity().GetActiveWeapon(), "m_ModelName")
841 local customWeapon = FindCustomWeapon(weaponModel)
842 if(customWeapon != null){
843 CallKeyPressFunctions(player, scope, Keys.ATTACK, "Attack")
844 CallKeyPressFunctions(player, scope, Keys.JUMP, "Jump")
845 CallKeyPressFunctions(player, scope, Keys.CROUCH, "Crouch")
846 CallKeyPressFunctions(player, scope, Keys.FORWARD, "Forward")
847 CallKeyPressFunctions(player, scope, Keys.BACKWARD, "Backward")
848 CallKeyPressFunctions(player, scope, Keys.USE, "Use")
849 CallKeyPressFunctions(player, scope, Keys.LEFT, "Left")
850 CallKeyPressFunctions(player, scope, Keys.RIGHT, "Right")
851 CallKeyPressFunctions(player, scope, Keys.ATTACK2, "Attack2")
852 CallKeyPressFunctions(player, scope, Keys.RELOAD, "Reload")
853 CallKeyPressFunctions(player, scope, Keys.ALT1, "Alt1")
854 CallKeyPressFunctions(player, scope, Keys.ALT2, "Alt2")
855 CallKeyPressFunctions(player, scope, Keys.SHOWSCORES, "Showscores")
856 CallKeyPressFunctions(player, scope, Keys.SPEED, "Speed")
857 CallKeyPressFunctions(player, scope, Keys.WALK, "Walk")
858 CallKeyPressFunctions(player, scope, Keys.ZOOM, "Zoom")
859 CallKeyPressFunctions(player, scope, Keys.GRENADE1, "Grenade1")
860 CallKeyPressFunctions(player, scope, Keys.GRENADE2, "Grenade2")
861 CallKeyPressFunctions(player, scope, Keys.LOOKSPIN, "Lookspin")
862
863 player.SetLastWeapon(player.GetEntity().GetActiveWeapon())
864 } else {
865 player.SetLastWeapon(player.GetEntity().GetActiveWeapon())
866 }
867 CallWeaponEquipFunctions(player, weaponModel)
868
869
870 local currentWeapons = []
871 local newWeapons = []
872 local droppedWeapons = player.GetLastWeaponsArray()
873
874 local inventoryIndex = 0
875 local item = null
876
877 while(inventoryIndex < 5){
878 item = NetProps.GetPropEntityArray(player.GetEntity(), "m_hMyWeapons", inventoryIndex)
879 if(item != null){
880 currentWeapons.append(item)
881 newWeapons.append(item)
882 }
883 inventoryIndex += 1
884 }
885
886 if(player.GetLastWeaponsArray() == null){
887 droppedWeapons = currentWeapons
888 }
889
890 for(local i=0;i < droppedWeapons.len();i+=1){
891 for(local j=0;j < newWeapons.len();j+=1){
892 if(i < droppedWeapons.len() && droppedWeapons[i] != null){
893 if(newWeapons != null && droppedWeapons != null && newWeapons[j] != null && droppedWeapons[i] != null && newWeapons[j].IsValid() && droppedWeapons[i].IsValid() && newWeapons[j].GetEntityIndex() == droppedWeapons[i].GetEntityIndex()){
894 newWeapons.remove(j)
895 droppedWeapons.remove(i)
896 if(i != 0){
897 i -= 1
898 }
899 j -= 1
900 }
901 }
902 }
903 }
904
905 if(newWeapons.len() > 0) {
906 foreach(ent in newWeapons){
907 foreach(weapon in customWeapons){
908 if(NetProps.GetPropString(ent, "m_ModelName") == weapon.GetViewmodel()){
909 CallFunction(weapon.GetScope(), "OnPickup", ent, player.GetEntity())
910 }
911 }
912 }
913 }
914 if(droppedWeapons.len() > 0){
915 foreach(ent in droppedWeapons){
916 foreach(weapon in customWeapons){
917 if(NetProps.GetPropString(ent, "m_ModelName") == weapon.GetWorldModel()){
918 CallFunction(weapon.GetScope(), "OnDrop", ent, player.GetEntity())
919 }
920 }
921 }
922 }
923 if(newWeapons.len() > 0 || droppedWeapons.len() > 0){
924 foreach(scope in hookScripts){
925 CallInventoryChangeFunction(scope, player.GetEntity(), droppedWeapons, newWeapons)
926 }
927 }
928
929 player.SetLastWeaponsArray(currentWeapons)
930 }
931 }
932 }
933 }
934
935 for(local i=0; i<tasks.len(); i+=1){
936 if(tasks[i].ReachedTime()){
937 try{
938 tasks[i].CallFunction()
939 } catch(e){
940 printl(e)
941 }
942 tasks.remove(i)
943 i -= 1
944 }
945 }
946}
947
948/**
949 * Adds various useful methods to common classes such as CBaseEntity and CTerrorPlayer
950 */
951function IncludeImprovedMethods(){
952 improvedMethods = true
953
954 local func = function(){
955 CBaseEntity["HasProp"] <- function(propertyName){return NetProps.HasProp(this, propertyName)}
956 CBaseEntity["GetPropType"] <- function(propertyName){return NetProps.GetPropType(this, propertyName)}
957 CBaseEntity["GetPropArraySize"] <- function(propertyName){return NetProps.GetPropArraySize(this, propertyName)}
958
959 CBaseEntity["GetPropInt"] <- function(propertyName){return NetProps.GetPropInt(this, propertyName)}
960 CBaseEntity["GetPropEntity"] <- function(propertyName){return NetProps.GetPropEntity(this, propertyName)}
961 CBaseEntity["GetPropString"] <- function(propertyName){return NetProps.GetPropString(this, propertyName)}
962 CBaseEntity["GetPropFloat"] <- function(propertyName){return NetProps.GetPropFloat(this, propertyName)}
963 CBaseEntity["GetPropVector"] <- function(propertyName){return NetProps.GetPropVector(this, propertyName)}
964 CBaseEntity["SetPropInt"] <- function(propertyName, value){NetProps.SetPropInt(this, propertyName, value)}
965 CBaseEntity["SetPropEntity"] <- function(propertyName, value){NetProps.SetPropEntity(this, propertyName, value)}
966 CBaseEntity["SetPropString"] <- function(propertyName, value){NetProps.SetPropString(this, propertyName, value)}
967 CBaseEntity["SetPropFloat"] <- function(propertyName, value){NetProps.SetPropFloat(this, propertyName, value)}
968 CBaseEntity["SetPropVector"] <- function(propertyName, value){NetProps.SetPropVector(this, propertyName, value)}
969
970 CBaseEntity["GetPropIntArray"] <- function(propertyName, index){return NetProps.GetPropIntArray(this, propertyName, index)}
971 CBaseEntity["GetPropEntityArray"] <- function(propertyName, index){return NetProps.GetPropEntityArray(this, propertyName, index)}
972 CBaseEntity["GetPropStringArray"] <- function(propertyName, index){return NetProps.GetPropStringArray(this, propertyName, index)}
973 CBaseEntity["GetPropFloatArray"] <- function(propertyName, index){return NetProps.GetPropFloatArray(this, propertyName, index)}
974 CBaseEntity["GetPropVectorArray"] <- function(propertyName, index){return NetProps.GetPropVectorArray(this, propertyName, index)}
975 CBaseEntity["SetPropIntArray"] <- function(propertyName, index, value){NetProps.SetPropIntArray(this, propertyName, value, index)}
976 CBaseEntity["SetPropEntityArray"] <- function(propertyName, index, value){NetProps.SetPropEntityArray(this, propertyName, value, index)}
977 CBaseEntity["SetPropStringArray"] <- function(propertyName, index, value){NetProps.SetPropStringArray(this, propertyName, value, index)}
978 CBaseEntity["SetPropFloatArray"] <- function(propertyName, index, value){NetProps.SetPropFloatArray(this, propertyName, value, index)}
979 CBaseEntity["SetPropVectorArray"] <- function(propertyName, index, value){NetProps.SetPropVectorArray(this, propertyName, value, index)}
980
981 CBaseEntity["SetProp"] <- function(propertyName, value, index = null){
982 if(GetPropType(propertyName) == "integer"){
983 if(GetPropArraySize(propertyName) > 0){
984 SetPropIntArray(propertyName, index, value)
985 } else {
986 SetPropInt(propertyName, value)
987 }
988 } else if(GetPropType(propertyName) == "float"){
989 if(GetPropArraySize(propertyName) > 0){
990 SetPropFloatArray(propertyName, index, value)
991 } else {
992 SetPropFloat(propertyName, value)
993 }
994 } else if(GetPropType(propertyName) == "Vector"){
995 if(GetPropArraySize(propertyName) > 0){
996 SetPropVectorArray(propertyName, index, value)
997 } else {
998 SetPropVector(propertyName, value)
999 }
1000 } else if(GetPropType(propertyName) == "string"){
1001 if(GetPropArraySize(propertyName) > 0){
1002 SetPropStringArray(propertyName, index, value)
1003 } else {
1004 SetPropString(propertyName, value)
1005 }
1006 }
1007 }
1008 CBaseEntity["GetProp"] <- function(propertyName, index = null){
1009 if(GetPropType(propertyName) == "integer"){
1010 if(GetPropArraySize(propertyName) > 0){
1011 return GetPropIntArray(propertyName, index)
1012 } else {
1013 return GetPropInt(propertyName)
1014 }
1015 } else if(GetPropType(propertyName) == "float"){
1016 if(GetPropArraySize(propertyName) > 0){
1017 return GetPropFloatArray(propertyName, index)
1018 } else {
1019 return GetPropFloat(propertyName)
1020 }
1021 } else if(GetPropType(propertyName) == "Vector"){
1022 if(GetPropArraySize(propertyName) > 0){
1023 return GetPropVectorArray(propertyName, index)
1024 } else {
1025 return GetPropVector(propertyName)
1026 }
1027 } else if(GetPropType(propertyName) == "string"){
1028 if(GetPropArraySize(propertyName) > 0){
1029 return GetPropStringArray(propertyName, index)
1030 } else {
1031 return GetPropString(propertyName)
1032 }
1033 }
1034 }
1035
1036 CBaseEntity["GetModelIndex"] <- function(){return GetPropInt("m_nModelIndex")}
1037 CBaseEntity["GetModelName"] <- function(){return GetPropString("m_ModelName")}
1038 CBaseEntity["SetName"] <- function(name){SetPropString("m_iName", name)}
1039
1040 CBaseEntity["GetFriction"] <- function(){return GetFriction(this)}
1041 CBaseEntity["GetPhysVelocity"] <- function(){return GetPhysVelocity(this)}
1042
1043 CBaseEntity["GetFlags"] <- function(){return GetPropInt("m_fFlags")}
1044 CBaseEntity["SetFlags"] <- function(flag){SetPropInt("m_fFlags", flag)}
1045 CBaseEntity["AddFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") | flag)}
1046 CBaseEntity["RemoveFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") & ~flag)}
1047 CBaseEntity["HasFlag"] <- function(flag){return GetFlags() & flag}
1048
1049 CBaseEntity["GetMoveType"] <- function(){return GetPropInt("movetype")}
1050 CBaseEntity["SetMoveType"] <- function(type){SetPropInt("movetype", type)}
1051
1052 CBaseEntity["GetSpawnflags"] <- function(){return GetPropInt("m_spawnflags")}
1053 CBaseEntity["SetSpawnFlags"] <- function(flags){SetPropInt("m_spawnflags", flags)}
1054
1055 CBaseEntity["GetGlowType"] <- function(){return GetPropInt("m_Glow.m_iGlowType")}
1056 CBaseEntity["SetGlowType"] <- function(type){SetPropInt("m_Glow.m_iGlowType", type)}
1057
1058 CBaseEntity["GetGlowRange"] <- function(){return GetPropInt("m_Glow.m_nGlowRange")}
1059 CBaseEntity["SetGlowRange"] <- function(range){SetPropInt("m_Glow.m_nGlowRange", range)}
1060
1061 CBaseEntity["GetGlowRangeMin"] <- function(){return GetPropInt("m_Glow.m_nGlowRangeMin")}
1062 CBaseEntity["SetGlowRangeMin"] <- function(range){SetPropInt("m_Glow.m_nGlowRangeMin", range)}
1063
1064 CBaseEntity["GetGlowColor"] <- function(){return GetPropInt("m_Glow.m_glowColorOverride")}
1065 CBaseEntity["SetGlowColor"] <- function(r, g, b){
1066 local color = r
1067 color += 256 * g
1068 color += 65536 * b
1069 SetPropInt("m_Glow.m_glowColorOverride", color)
1070 }
1071 CBaseEntity["SetGlowColorVector"] <- function(vector){
1072 local color = vector.x
1073 color += 256 * vector.y
1074 color += 65536 * vector.z
1075 SetPropInt("m_Glow.m_glowColorOverride", color)
1076 }
1077 CBaseEntity["ResetGlowColor"] <- function(){SetPropInt("m_Glow.m_glowColorOverride", -1)}
1078
1079 CBaseEntity["SetTeam"] <- function(team){SetPropInt("m_iTeamNum", team.tointeger())}
1080 CBaseEntity["GetTeam"] <- function(){return GetPropInt("m_iTeamNum")}
1081
1082 CBaseEntity["GetGlowFlashing"] <- function(){return GetPropInt("m_Glow.m_bFlashing")}
1083 CBaseEntity["SetGlowFlashing"] <- function(flashing){SetPropInt("m_Glow.m_bFlashing", flashing)}
1084
1085 CBaseEntity["GetFlowDistance"] <- function(){return GetFlowDistanceForPosition(GetOrigin())}
1086 CBaseEntity["GetFlowPercent"] <- function(){return GetFlowPercentForPosition(GetOrigin())}
1087
1088 CBaseEntity["PlaySound"] <- function(soundName){EmitSoundOn(soundName, this)}
1089 CBaseEntity["StopSound"] <- function(soundName){StopSoundOn(soundName, this)}
1090
1091 CBaseEntity["Input"] <- function(input, value = "", delay = 0, activator = null){DoEntFire("!self", input.tostring(), value.tostring(), delay.tofloat(), activator, this)}
1092 CBaseEntity["SetAlpha"] <- function(alpha){Input("Alpha", alpha)}
1093 CBaseEntity["Enable"] <- function(){Input("Enable")}
1094 CBaseEntity["Disable"] <- function(){Input("Disable")}
1095 CBaseEntity["GetValidatedScriptScope"] <- function(){
1096 ValidateScriptScope()
1097 return GetScriptScope()
1098 }
1099
1100
1101
1102 CBaseAnimating["GetMoveType"] <- function(){return GetPropInt("movetype")}
1103 CBaseAnimating["SetMoveType"] <- function(type){SetPropInt("movetype", type)}
1104
1105 CBaseAnimating["PlaySound"] <- function(soundName){EmitSoundOn(soundName, this)}
1106 CBaseAnimating["StopSound"] <- function(soundName){StopSoundOn(soundName, this)}
1107
1108 CBaseAnimating["GetFlags"] <- function(){return GetPropInt("m_fFlags")}
1109 CBaseAnimating["SetFlags"] <- function(flag){SetPropInt("m_fFlags", flag)}
1110 CBaseAnimating["AddFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") | flag)}
1111 CBaseAnimating["RemoveFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") & ~flag)}
1112 CBaseAnimating["HasFlag"] <- function(flag){return GetFlags() & flag}
1113
1114 CBaseAnimating["GetSpawnflags"] <- function(){return GetPropInt("m_spawnflags")}
1115 CBaseAnimating["SetSpawnFlags"] <- function(flags){SetPropInt("m_spawnflags", flags)}
1116
1117 CBaseAnimating["GetGlowType"] <- function(){return GetPropInt("m_Glow.m_iGlowType")}
1118 CBaseAnimating["SetGlowType"] <- function(type){SetPropInt("m_Glow.m_iGlowType", type)}
1119
1120 CBaseAnimating["GetGlowRange"] <- function(){return GetPropInt("m_Glow.m_nGlowRange")}
1121 CBaseAnimating["SetGlowRange"] <- function(range){SetPropInt("m_Glow.m_nGlowRange", range)}
1122
1123 CBaseAnimating["GetGlowRangeMin"] <- function(){return GetPropInt("m_Glow.m_nGlowRangeMin")}
1124 CBaseAnimating["SetGlowRangeMin"] <- function(range){SetPropInt("m_Glow.m_nGlowRangeMin", range)}
1125
1126 CBaseAnimating["GetGlowColor"] <- function(){return GetPropInt("m_Glow.m_glowColorOverride")}
1127 CBaseAnimating["SetGlowColor"] <- function(r, g, b){
1128 local color = r
1129 color += 256 * g
1130 color += 65536 * b
1131 SetPropInt("m_Glow.m_glowColorOverride", color)
1132 }
1133 CBaseAnimating["SetGlowColorVector"] <- function(vector){
1134 local color = vector.x
1135 color += 256 * vector.y
1136 color += 65536 * vector.z
1137 SetPropInt("m_Glow.m_glowColorOverride", color)
1138 }
1139 CBaseAnimating["ResetGlowColor"] <- function(){SetPropInt("m_Glow.m_glowColorOverride", -1)}
1140
1141 CBaseAnimating["GetSequence"] <- function(){return GetPropInt("m_nSequence")}
1142 CBaseAnimating["GetValidatedScriptScope"] <- function(){
1143 ValidateScriptScope()
1144 return GetScriptScope()
1145 }
1146
1147 CBaseAnimating["SetTeam"] <- function(team){SetPropInt("m_iTeamNum", team.tointeger())}
1148 CBaseAnimating["GetTeam"] <- function(){return GetPropInt("m_iTeamNum")}
1149
1150 CBaseAnimating["Input"] <- function(input, value = "", delay = 0, activator = null){DoEntFire("!self", input.tostring(), value.tostring(), delay.tofloat(), activator, this)}
1151 CBaseAnimating["SetAlpha"] <- function(alpha){Input("Alpha", alpha)}
1152 CBaseAnimating["Enable"] <- function(){Input("Enable")}
1153 CBaseAnimating["Disable"] <- function(){Input("Disable")}
1154
1155 CBaseAnimating["GetMoveType"] <- function(){return GetPropInt("movetype")}
1156 CBaseAnimating["SetMoveType"] <- function(type){SetPropInt("movetype", type)}
1157
1158 CBaseAnimating["GetModelIndex"] <- function(){return GetPropInt("m_nModelIndex")}
1159 CBaseAnimating["GetModelName"] <- function(){return GetPropString("m_ModelName")}
1160 CBaseAnimating["SetName"] <- function(name){SetPropString("m_iName", name)}
1161
1162 CBaseAnimating["GetFriction"] <- function(){return GetFriction(this)}
1163
1164 CBaseAnimating["HasProp"] <- function(propertyName){return NetProps.HasProp(this, propertyName)}
1165 CBaseAnimating["GetPropType"] <- function(propertyName){return NetProps.GetPropType(this, propertyName)}
1166 CBaseAnimating["GetPropArraySize"] <- function(propertyName){return NetProps.GetPropArraySize(this, propertyName)}
1167
1168 CBaseAnimating["GetPropInt"] <- function(propertyName){return NetProps.GetPropInt(this, propertyName)}
1169 CBaseAnimating["GetPropEntity"] <- function(propertyName){return NetProps.GetPropEntity(this, propertyName)}
1170 CBaseAnimating["GetPropString"] <- function(propertyName){return NetProps.GetPropString(this, propertyName)}
1171 CBaseAnimating["GetPropFloat"] <- function(propertyName){return NetProps.GetPropFloat(this, propertyName)}
1172 CBaseAnimating["GetPropVector"] <- function(propertyName){return NetProps.GetPropVector(this, propertyName)}
1173 CBaseAnimating["SetPropInt"] <- function(propertyName, value){return NetProps.SetPropInt(this, propertyName, value)}
1174 CBaseAnimating["SetPropEntity"] <- function(propertyName, value){return NetProps.SetPropEntity(this, propertyName, value)}
1175 CBaseAnimating["SetPropString"] <- function(propertyName, value){return NetProps.SetPropString(this, propertyName, value)}
1176 CBaseAnimating["SetPropFloat"] <- function(propertyName, value){return NetProps.SetPropFloat(this, propertyName, value)}
1177 CBaseAnimating["SetPropVector"] <- function(propertyName, value){return NetProps.SetPropVector(this, propertyName, value)}
1178
1179 CBaseAnimating["GetPropIntArray"] <- function(propertyName, index){return NetProps.GetPropIntArray(this, propertyName, index)}
1180 CBaseAnimating["GetPropEntityArray"] <- function(propertyName, index){return NetProps.GetPropEntityArray(this, propertyName, index)}
1181 CBaseAnimating["GetPropStringArray"] <- function(propertyName, index){return NetProps.GetPropStringArray(this, propertyName, index)}
1182 CBaseAnimating["GetPropFloatArray"] <- function(propertyName, index){return NetProps.GetPropFloatArray(this, propertyName, index)}
1183 CBaseAnimating["GetPropVectorArray"] <- function(propertyName, index){return NetProps.GetPropVectorArray(this, propertyName, index)}
1184 CBaseAnimating["SetPropIntArray"] <- function(propertyName, index, value){return NetProps.SetPropIntArray(this, propertyName, value, index)}
1185 CBaseAnimating["SetPropEntityArray"] <- function(propertyName, index, value){return NetProps.SetPropEntityArray(this, propertyName, value, index)}
1186 CBaseAnimating["SetPropStringArray"] <- function(propertyName, index, value){return NetProps.SetPropStringArray(this, propertyName, value, index)}
1187 CBaseAnimating["SetPropFloatArray"] <- function(propertyName, index, value){return NetProps.SetPropFloatArray(this, propertyName, value, index)}
1188 CBaseAnimating["SetPropVectorArray"] <- function(propertyName, index, value){return NetProps.SetPropVectorArray(this, propertyName, value, index)}
1189
1190 CBaseAnimating["SetProp"] <- function(propertyName, value, index = null){
1191 if(GetPropType(propertyName) == "integer"){
1192 if(GetPropArraySize(propertyName) > 0){
1193 SetPropIntArray(propertyName, index, value)
1194 } else {
1195 SetPropInt(propertyName, value)
1196 }
1197 } else if(GetPropType(propertyName) == "float"){
1198 if(GetPropArraySize(propertyName) > 0){
1199 SetPropFloatArray(propertyName, index, value)
1200 } else {
1201 SetPropFloat(propertyName, value)
1202 }
1203 } else if(GetPropType(propertyName) == "Vector"){
1204 if(GetPropArraySize(propertyName) > 0){
1205 SetPropVectorArray(propertyName, index, value)
1206 } else {
1207 SetPropVector(propertyName, value)
1208 }
1209 } else if(GetPropType(propertyName) == "string"){
1210 if(GetPropArraySize(propertyName) > 0){
1211 SetPropStringArray(propertyName, index, value)
1212 } else {
1213 SetPropString(propertyName, value)
1214 }
1215 }
1216 }
1217 CBaseAnimating["GetProp"] <- function(propertyName, index = null){
1218 if(GetPropType(propertyName) == "integer"){
1219 if(GetPropArraySize(propertyName) > 0){
1220 return GetPropIntArray(propertyName, index)
1221 } else {
1222 return GetPropInt(propertyName)
1223 }
1224 } else if(GetPropType(propertyName) == "float"){
1225 if(GetPropArraySize(propertyName) > 0){
1226 return GetPropFloatArray(propertyName, index)
1227 } else {
1228 return GetPropFloat(propertyName)
1229 }
1230 } else if(GetPropType(propertyName) == "Vector"){
1231 if(GetPropArraySize(propertyName) > 0){
1232 return GetPropVectorArray(propertyName, index)
1233 } else {
1234 return GetPropVector(propertyName)
1235 }
1236 } else if(GetPropType(propertyName) == "string"){
1237 if(GetPropArraySize(propertyName) > 0){
1238 return GetPropStringArray(propertyName, index)
1239 } else {
1240 return GetPropString(propertyName)
1241 }
1242 }
1243 }
1244
1245 CBaseAnimating["SetClip"] <- function(clip){SetPropInt("m_iClip1", clip)}
1246 CBaseAnimating["GetClip"] <- function(){return GetPropInt("m_iClip1")}
1247 CBaseAnimating["SetReserveAmmo"] <- function(ammo){SetPropInt("m_iExtraPrimaryAmmo", ammo)}
1248 CBaseAnimating["GetReserveAmmo"] <- function(){return GetPropInt("m_iExtraPrimaryAmmo")}
1249
1250
1251
1252 CTerrorPlayer["HasProp"] <- function(propertyName){return NetProps.HasProp(this, propertyName)}
1253 CTerrorPlayer["GetPropType"] <- function(propertyName){return NetProps.GetPropType(this, propertyName)}
1254 CTerrorPlayer["GetPropArraySize"] <- function(propertyName){return NetProps.GetPropArraySize(this, propertyName)}
1255
1256 CTerrorPlayer["GetPropInt"] <- function(propertyName){return NetProps.GetPropInt(this, propertyName)}
1257 CTerrorPlayer["GetPropEntity"] <- function(propertyName){return NetProps.GetPropEntity(this, propertyName)}
1258 CTerrorPlayer["GetPropString"] <- function(propertyName){return NetProps.GetPropString(this, propertyName)}
1259 CTerrorPlayer["GetPropFloat"] <- function(propertyName){return NetProps.GetPropFloat(this, propertyName)}
1260 CTerrorPlayer["GetPropVector"] <- function(propertyName){return NetProps.GetPropVector(this, propertyName)}
1261 CTerrorPlayer["SetPropInt"] <- function(propertyName, value){return NetProps.SetPropInt(this, propertyName, value)}
1262 CTerrorPlayer["SetPropEntity"] <- function(propertyName, value){return NetProps.SetPropEntity(this, propertyName, value)}
1263 CTerrorPlayer["SetPropString"] <- function(propertyName, value){return NetProps.SetPropString(this, propertyName, value)}
1264 CTerrorPlayer["SetPropFloat"] <- function(propertyName, value){return NetProps.SetPropFloat(this, propertyName, value)}
1265 CTerrorPlayer["SetPropVector"] <- function(propertyName, value){return NetProps.SetPropVector(this, propertyName, value)}
1266
1267 CTerrorPlayer["GetPropIntArray"] <- function(propertyName, index){return NetProps.GetPropIntArray(this, propertyName, index)}
1268 CTerrorPlayer["GetPropEntityArray"] <- function(propertyName, index){return NetProps.GetPropEntityArray(this, propertyName, index)}
1269 CTerrorPlayer["GetPropStringArray"] <- function(propertyName, index){return NetProps.GetPropStringArray(this, propertyName, index)}
1270 CTerrorPlayer["GetPropFloatArray"] <- function(propertyName, index){return NetProps.GetPropFloatArray(this, propertyName, index)}
1271 CTerrorPlayer["GetPropVectorArray"] <- function(propertyName, index){return NetProps.GetPropVectorArray(this, propertyName, index)}
1272 CTerrorPlayer["SetPropIntArray"] <- function(propertyName, index, value){return NetProps.SetPropIntArray(this, propertyName, value, index)}
1273 CTerrorPlayer["SetPropEntityArray"] <- function(propertyName, index, value){return NetProps.SetPropEntityArray(this, propertyName, value, index)}
1274 CTerrorPlayer["SetPropStringArray"] <- function(propertyName, index, value){return NetProps.SetPropStringArray(this, propertyName, value, index)}
1275 CTerrorPlayer["SetPropFloatArray"] <- function(propertyName, index, value){return NetProps.SetPropFloatArray(this, propertyName, value, index)}
1276 CTerrorPlayer["SetPropVectorArray"] <- function(propertyName, index, value){return NetProps.SetPropVectorArray(this, propertyName, value, index)}
1277
1278 CTerrorPlayer["SetProp"] <- function(propertyName, value, index = null){
1279 if(GetPropType(propertyName) == "integer"){
1280 if(GetPropArraySize(propertyName) > 0){
1281 SetPropIntArray(propertyName, index, value)
1282 } else {
1283 SetPropInt(propertyName, value)
1284 }
1285 } else if(GetPropType(propertyName) == "float"){
1286 if(GetPropArraySize(propertyName) > 0){
1287 SetPropFloatArray(propertyName, index, value)
1288 } else {
1289 SetPropFloat(propertyName, value)
1290 }
1291 } else if(GetPropType(propertyName) == "Vector"){
1292 if(GetPropArraySize(propertyName) > 0){
1293 SetPropVectorArray(propertyName, index, value)
1294 } else {
1295 SetPropVector(propertyName, value)
1296 }
1297 } else if(GetPropType(propertyName) == "string"){
1298 if(GetPropArraySize(propertyName) > 0){
1299 SetPropStringArray(propertyName, index, value)
1300 } else {
1301 SetPropString(propertyName, value)
1302 }
1303 }
1304 }
1305 CTerrorPlayer["GetProp"] <- function(propertyName, index = null){
1306 if(GetPropType(propertyName) == "integer"){
1307 if(GetPropArraySize(propertyName) > 0){
1308 return GetPropIntArray(propertyName, index)
1309 } else {
1310 return GetPropInt(propertyName)
1311 }
1312 } else if(GetPropType(propertyName) == "float"){
1313 if(GetPropArraySize(propertyName) > 0){
1314 return GetPropFloatArray(propertyName, index)
1315 } else {
1316 return GetPropFloat(propertyName)
1317 }
1318 } else if(GetPropType(propertyName) == "Vector"){
1319 if(GetPropArraySize(propertyName) > 0){
1320 return GetPropVectorArray(propertyName, index)
1321 } else {
1322 return GetPropVector(propertyName)
1323 }
1324 } else if(GetPropType(propertyName) == "string"){
1325 if(GetPropArraySize(propertyName) > 0){
1326 return GetPropStringArray(propertyName, index)
1327 } else {
1328 return GetPropString(propertyName)
1329 }
1330 }
1331 }
1332
1333 CTerrorPlayer["Input"] <- function(input, value = "", delay = 0, activator = null){DoEntFire("!self", input.tostring(), value.tostring(), delay.tofloat(), activator, this)}
1334 CTerrorPlayer["SetAlpha"] <- function(alpha){Input("Alpha", alpha)}
1335 CTerrorPlayer["Enable"] <- function(){Input("Enable")}
1336 CTerrorPlayer["Disable"] <- function(){Input("Disable")}
1337
1338 CTerrorPlayer["GetValidatedScriptScope"] <- function(){
1339 ValidateScriptScope()
1340 return GetScriptScope()
1341 }
1342
1343 CTerrorPlayer["GetMoveType"] <- function(){return GetPropInt("movetype")}
1344 CTerrorPlayer["SetMoveType"] <- function(type){SetPropInt("movetype", type)}
1345
1346 CTerrorPlayer["GetFlags"] <- function(){return GetPropInt("m_fFlags")}
1347 CTerrorPlayer["SetFlags"] <- function(flag){SetPropInt("m_fFlags", flag)}
1348 CTerrorPlayer["AddFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") | flag)}
1349 CTerrorPlayer["RemoveFlag"] <- function(flag){SetPropInt("m_fFlags", GetPropInt("m_fFlags") & ~flag)}
1350 CTerrorPlayer["HasFlag"] <- function(flag){return GetFlags() & flag}
1351
1352 CTerrorPlayer["GetGlowType"] <- function(){return GetPropInt("m_Glow.m_iGlowType")}
1353 CTerrorPlayer["SetGlowType"] <- function(type){SetPropInt("m_Glow.m_iGlowType", type)}
1354
1355 CTerrorPlayer["GetGlowRange"] <- function(){return GetPropInt("m_Glow.m_nGlowRange")}
1356 CTerrorPlayer["SetGlowRange"] <- function(range){SetPropInt("m_Glow.m_nGlowRange", range)}
1357
1358 CTerrorPlayer["GetGlowRangeMin"] <- function(){return GetPropInt("m_Glow.m_nGlowRangeMin")}
1359 CTerrorPlayer["SetGlowRangeMin"] <- function(range){SetPropInt("m_Glow.m_nGlowRangeMin", range)}
1360
1361 CTerrorPlayer["GetGlowColor"] <- function(){return GetPropInt("m_Glow.m_glowColorOverride")}
1362 CTerrorPlayer["SetGlowColor"] <- function(r, g, b){
1363 local color = r
1364 color += 256 * g
1365 color += 65536 * b
1366 SetPropInt("m_Glow.m_glowColorOverride", color)
1367 }
1368 CTerrorPlayer["SetGlowColorVector"] <- function(vector){
1369 local color = vector.x
1370 color += 256 * vector.y
1371 color += 65536 * vector.z
1372 SetPropInt("m_Glow.m_glowColorOverride", color)
1373 }
1374 CTerrorPlayer["ResetGlowColor"] <- function(){SetPropInt("m_Glow.m_glowColorOverride", -1)}
1375
1376 CTerrorPlayer["GetModelIndex"] <- function(){return GetPropInt("m_nModelIndex")}
1377 CTerrorPlayer["GetModelName"] <- function(){return GetPropString("m_ModelName")}
1378
1379 CTerrorPlayer["SetName"] <- function(name){SetPropString("m_iName", name)}
1380
1381 CTerrorPlayer["GetFriction"] <- function(){return GetFriction(this)}
1382
1383 CTerrorPlayer["SetTeam"] <- function(team){SetPropInt("m_iTeamNum", team.tointeger())}
1384 CTerrorPlayer["GetTeam"] <- function(){return GetPropInt("m_iTeamNum")}
1385
1386 CTerrorPlayer["GetInterp"] <- function(){return GetPropFloat("m_fLerpTime")}
1387
1388 CTerrorPlayer["GetUpdateRate"] <- function(){return GetPropInt("m_nUpdateRate")}
1389
1390 CTerrorPlayer["SetModelScale"] <- function(modelScale){SetPropFloat("m_flModelScale", modelScale.tofloat())}
1391 CTerrorPlayer["GetModelScale"] <- function(){return GetPropFloat("m_flModelScale")}
1392
1393 CTerrorPlayer["SetThirdperson"] <- function(thirdperson){SetPropFloat("m_TimeForceExternalView", thirdperson ? 2147483647 : 0)}
1394 CTerrorPlayer["IsInThirdperson"] <- function(){return Time() < GetPropFloat("m_TimeForceExternalView")}
1395
1396 CTerrorPlayer["GetTongueVictim"] <- function(){return GetPropEntity("m_tongueVictim")}
1397 CTerrorPlayer["GetTongueAttacker"] <- function(){return GetPropEntity("m_tongueOwner")}
1398 CTerrorPlayer["GetPounceVictim"] <- function(){return GetPropEntity("m_pounceVictim")}
1399 CTerrorPlayer["GetPounceAttacker"] <- function(){return GetPropEntity("m_pounceAttacker")}
1400 CTerrorPlayer["GetLeapVictim"] <- function(){return GetPropEntity("m_jockeyVictim")}
1401 CTerrorPlayer["GetLeapAttacker"] <- function(){return GetPropEntity("m_jockeyAttacker")}
1402 CTerrorPlayer["GetChargeVictim"] <- function(){return GetPropEntity("m_jockeyVictim")}
1403 CTerrorPlayer["GetChargeAttacker"] <- function(){return GetPropEntity("m_jockeyAttacker")}
1404
1405 CTerrorPlayer["AddDisabledButton"] <- function(disabledButton){SetPropInt("m_afButtonDisabled", GetPropInt("m_afButtonDisabled") | disabledButton.tointeger())}
1406 CTerrorPlayer["RemoveDisabledButton"] <- function(disabledButton){SetPropInt("m_afButtonDisabled", GetPropInt("m_afButtonDisabled") & ~disabledButton.tointeger())}
1407 CTerrorPlayer["SetDisabledButtons"] <- function(disabledButtons){SetPropInt("m_afButtonDisabled", disabledButtons.tointeger())}
1408 CTerrorPlayer["GetDisabledButtons"] <- function(){return GetPropInt("m_afButtonDisabled")}
1409 CTerrorPlayer["HasDisabledButton"] <- function(disabledButton){return GetDisabledButtons() & disabledButton}
1410
1411 CTerrorPlayer["AddForcedButton"] <- function(forcedButton){SetPropInt("m_afButtonForced", GetPropInt("m_afButtonForced") | disabledButton.tointeger())}
1412 CTerrorPlayer["RemoveForcedButton"] <- function(forcedButton){SetPropInt("m_afButtonForced", GetPropInt("m_afButtonForced") & ~disabledButton.tointeger())}
1413 CTerrorPlayer["SetForcedButtons"] <- function(forcedButtons){SetPropInt("m_afButtonForced", disabledButtons.tointeger())}
1414 CTerrorPlayer["GetForcedButtons"] <- function(){return GetPropInt("m_afButtonForced")}
1415 CTerrorPlayer["HasForcedButton"] <- function(forcedButton){return GetForcedButtons() & forcedButton}
1416
1417 CTerrorPlayer["SetPresentAtSurvivalStart"] <- function(presentAtSurvivalStart){SetPropInt("m_bWasPresentAtSurvivalStart", presentAtSurvivalStart.tointeger())}
1418 CTerrorPlayer["WasPresentAtSurvivalStart"] <- function(){return GetPropInt("m_bWasPresentAtSurvivalStart")}
1419
1420 CTerrorPlayer["SetGhost"] <- function(ghost){SetPropInt("m_isGhost", ghost.tointeger())}
1421
1422 CTerrorPlayer["SetUsingMountedGun"] <- function(usingMountedGun){SetPropInt("m_usingMountedGun", usingMountedGun.tointeger())}
1423 CTerrorPlayer["IsUsingMountedGun"] <- function(){return GetPropInt("m_usingMountedGun")}
1424
1425 CTerrorPlayer["IsFirstManOut"] <- function(){return GetPropInt("m_bIsFirstManOut")}
1426
1427 CTerrorPlayer["GetReviveCount"] <- function(){return GetPropInt("m_currentReviveCount")}
1428
1429 CTerrorPlayer["IsProneTongueDrag"] <- function(){return GetPropInt("m_isProneTongueDrag")}
1430 CTerrorPlayer["ReachedTongueOwner"] <- function(){return GetPropInt("m_reachedTongueOwner")}
1431 CTerrorPlayer["IsHangingFromTongue"] <- function(){return GetPropInt("m_isHangingFromTongue")}
1432
1433 CTerrorPlayer["SetReviveTarget"] <- function(reviveTarget){SetPropEntity("m_reviveTarget", reviveTarget)}
1434 CTerrorPlayer["GetReviveTarget"] <- function(){return GetPropEntity("m_reviveTarget")}
1435 CTerrorPlayer["SetReviveOwner"] <- function(reviveOwner){SetPropEntity("m_reviveOwner", reviveOwner)}
1436 CTerrorPlayer["GetReviveOwner"] <- function(){return GetPropEntity("m_reviveOwner")}
1437
1438 CTerrorPlayer["SetCurrentUseAction"] <- function(currentUseAction){SetPropInt("m_iCurrentUseAction", currentUseAction.tointeger())}
1439 CTerrorPlayer["GetCurrentUseAction"] <- function(){return GetPropInt("m_iCurrentUseAction")}
1440 CTerrorPlayer["SetUseActionTarget"] <- function(useActionTarget){SetPropEntity("m_useActionTarget", useActionTarget)}
1441 CTerrorPlayer["GetUseActionTarget"] <- function(){return GetPropEntity("m_useActionTarget")}
1442 CTerrorPlayer["SetUseActionOwner"] <- function(useActionOwner){SetPropEntity("m_useActionOwner", useActionOwner)}
1443 CTerrorPlayer["GetUseActionOwner"] <- function(){return GetPropEntity("m_useActionOwner")}
1444
1445 CTerrorPlayer["SetNightvisionEnabled"] <- function(nightvisionEnabled){SetPropInt("m_bNightVisionOn", nightvisionEnabled.tointeger())}
1446 CTerrorPlayer["IsNightvisionEnabled"] <- function(){return GetPropInt("m_bNightVisionOn")}
1447
1448 CTerrorPlayer["SetTimescale"] <- function(timescale){SetPropFloat("m_flLaggedMovementValue", timescale.tofloat())}
1449 CTerrorPlayer["GetTimescale"] <- function(){return GetPropFloat("m_flLaggedMovementValue")}
1450
1451 CTerrorPlayer["SetDrawViewmodel"] <- function(drawViewmodel){SetPropInt("m_bDrawViewmodel", drawViewmodel.tointeger())}
1452 CTerrorPlayer["GetDrawViewmodel"] <- function(){return GetPropInt("m_bDrawViewmodel")}
1453
1454 CTerrorPlayer["SetFallVelocity"] <- function(fallVelocity){SetPropFloat("m_flFallVelocity", fallVelocity)}
1455 CTerrorPlayer["GetFallVelocity"] <- function(){return GetPropFloat("m_flFallVelocity")}
1456
1457 CTerrorPlayer["SetHideHUD"] <- function(hideHUD){SetPropInt("m_iHideHUD", hideHUD.tointeger())}
1458 CTerrorPlayer["GetHideHUD"] <- function(){return GetPropInt("m_iHideHUD")}
1459
1460 CTerrorPlayer["SetViewmodel"] <- function(viewmodel){SetPropEntity("m_hViewModel", viewmodel)}
1461 CTerrorPlayer["GetViewmodel"] <- function(){return GetPropEntity("m_hViewModel")}
1462
1463 CTerrorPlayer["SetZoom"] <- function(zoom){SetPropInt("m_iFOV", zoom.tointeger())}
1464 CTerrorPlayer["GetZoom"] <- function(){return GetPropInt("m_iFOV")}
1465
1466 CTerrorPlayer["SetForcedObserverMode"] <- function(forcedObserverMode){SetPropInt("m_bForcedObserverMode", forcedObserverMode.tointeger())}
1467 CTerrorPlayer["IsForcedObserverMode"] <- function(){return GetPropInt("m_bForcedObserverMode")}
1468 CTerrorPlayer["SetObserverTarget"] <- function(observerTarget){SetPropEntity("m_hObserverTarget", observerTarget)}
1469 CTerrorPlayer["GetObserverTarget"] <- function(){return GetPropEntity("m_hObserverTarget")}
1470 CTerrorPlayer["SetObserverLastMode"] <- function(observerLastMode){SetPropInt("m_iObserverLastMode", observerLastMode.tointeger())}
1471 CTerrorPlayer["GetObserverLastMode"] <- function(){return GetPropInt("m_iObserverLastMode")}
1472 CTerrorPlayer["SetObserverMode"] <- function(observerMode){SetPropInt("m_iObserverMode", observerMode.tointeger())}
1473 CTerrorPlayer["GetObserverMode"] <- function(){return GetPropInt("m_iObserverMode")}
1474
1475 CTerrorPlayer["SetSurvivorCharacter"] <- function(survivorCharacter){SetPropInt("m_survivorCharacter", survivorCharacter.tointeger())}
1476 CTerrorPlayer["GetSurvivorCharacter"] <- function(){return GetPropInt("m_survivorCharacter")}
1477
1478 CTerrorPlayer["IsCalm"] <- function(){return GetPropInt("m_isCalm")}
1479
1480 CTerrorPlayer["SetCustomAbility"] <- function(customAbility){SetPropEntity("m_customAbility", customAbility)}
1481 CTerrorPlayer["GetCustomAbility"] <- function(){return GetPropEntity("m_customAbility")}
1482
1483 CTerrorPlayer["SetSurvivorGlowEnabled"] <- function(survivorGlowEnabled){SetPropInt("m_bSurvivorGlowEnabled", survivorGlowEnabled.tointeger())}
1484
1485 CTerrorPlayer["GetIntensity"] <- function(){return GetPropInt("m_clientIntensity")}
1486
1487 CTerrorPlayer["IsFallingFromLedge"] <- function(){return GetPropInt("m_isFallingFromLedge")}
1488
1489 CTerrorPlayer["ClearJumpSuppression"] <- function(){SetPropFloat("m_jumpSupressedUntil", 0)}
1490 CTerrorPlayer["SuppressJump"] <- function(time){SetPropFloat("m_jumpSupressedUntil", Time() + time.tofloat())}
1491
1492 CTerrorPlayer["SetMaxHealth"] <- function(maxHealth){SetPropInt("m_iMaxHealth", maxHealth.tointeger())}
1493
1494 CTerrorPlayer["SetAirMovementRestricted"] <- function(airMovementRestricted){SetPropInt("m_airMovementRestricted", airMovementRestricted.tointeger())}
1495 CTerrorPlayer["GetAirMovementRestricted"] <- function(){return GetPropInt("m_airMovementRestricted")}
1496
1497 CTerrorPlayer["GetFlowDistance"] <- function(){return GetCurrentFlowDistanceForPlayer(this)}
1498 CTerrorPlayer["GetFlowPercent"] <- function(){return GetCurrentFlowPercentForPlayer(this)}
1499
1500 CTerrorPlayer["GetCharacterName"] <- function(){return GetCharacterDisplayName(this)}
1501
1502 CTerrorPlayer["Say"] <- function(message, teamOnly = false){::Say(this, message, teamOnly)}
1503
1504 CTerrorPlayer["IsBot"] <- function(){return IsPlayerABot(this)}
1505
1506 CTerrorPlayer["PickupObject"] <- function(entity){PickupObject(this, entity)}
1507
1508 CTerrorPlayer["SetAngles"] <- function(angles){
1509 local prevPlayerName = GetName()
1510 local playerName = UniqueString()
1511 SetName(playerName)
1512 local teleportEntity = SpawnEntityFromTable("point_teleport", {origin = GetOrigin(), angles = angles.ToKVString(), target = playerName, targetname = UniqueString()})
1513 DoEntFire("!self", "Teleport", "", 0, null, teleportEntity)
1514 DoEntFire("!self", "Kill", "", 0, null, teleportEntity)
1515 DoEntFire("!self", "AddOutput", "targetname " + prevPlayerName, 0.01, null, this)
1516 }
1517
1518 CTerrorPlayer["GetLifeState"] <- function(){return GetPropInt("m_lifeState")}
1519
1520 CTerrorPlayer["PlaySound"] <- function(soundName){EmitSoundOn(soundName, this)}
1521 CTerrorPlayer["StopSound"] <- function(soundName){StopSoundOn(soundName, this)}
1522
1523 CTerrorPlayer["PlaySoundOnClient"] <- function(soundName){EmitSoundOnClient(soundName, this)}
1524
1525 CTerrorPlayer["GetAmmo"] <- function(weapon){return GetPropIntArray("m_iAmmo", weapon.GetPropInt("m_iPrimaryAmmoType"))}
1526 CTerrorPlayer["SetAmmo"] <- function(weapon, ammo){SetPropIntArray("m_iAmmo", weapon.GetPropInt("m_iPrimaryAmmoType"), ammo)}
1527 }
1528
1529 if(Time() > 0.034){
1530 func()
1531 } else {
1532 DoNextTick(func)
1533 }
1534}
1535
1536/**
1537 * Registers a listener that will call a function when the given check function returns true
1538 */
1539function RegisterFunctionListener(checkFunction, callFunction, args, singleUse){
1540 local errorMessage = "Failed to register function listener"
1541 if(CheckType(checkFunction, VariableTypes.FUNCTION)){
1542 if(CheckType(callFunction, VariableTypes.FUNCTION)){
1543 if(CheckType(args, VariableTypes.TABLE)){
1544 if(CheckType(singleUse, VariableTypes.BOOLEAN)){
1545 functionListeners.append(FunctionListener(checkFunction, callFunction, args, singleUse))
1546 PrintInfo("Registered function listener")
1547 return true
1548 } else {
1549 PrintInvalidVarType(errorMessage, "singleUse", VariableTypes.BOOLEAN, typeof(singleUse))
1550 }
1551 } else {
1552 PrintInvalidVarType(errorMessage, "args", VariableTypes.TABLE, typeof(args))
1553 }
1554 } else {
1555 PrintInvalidVarType(errorMessage, "callFunction", VariableTypes.FUNCTION, typeof(callFunction))
1556 }
1557 } else {
1558 PrintInvalidVarType(errorMessage, "checkFunction", VariableTypes.FUNCTION, typeof(checkFunction))
1559 }
1560 return false
1561}
1562
1563/**
1564 * Registers a custom weapon hook
1565 */
1566function RegisterCustomWeapon(viewmodel, worldmodel, script){
1567 local errorMessage = "Failed to register custom weapon"
1568 if(CheckType(viewmodel, VariableTypes.STRING)){
1569 if(CheckType(worldmodel, VariableTypes.STRING)){
1570 if(CheckType(script, VariableTypes.STRING)){
1571 local errorMessage = "Failed to register a custom weapon script "
1572 local scriptScope = {}
1573 if(!IncludeScript(script, scriptScope)){
1574 PrintError(errorMessage + "(Could not include script)")
1575 return false
1576 }
1577 if(viewmodel.slice(viewmodel.len()-4) != ".mdl"){
1578 viewmodel = viewmodel + ".mdl"
1579 }
1580 if(worldmodel.slice(worldmodel.len()-4) != ".mdl"){
1581 worldmodel = worldmodel + ".mdl"
1582 }
1583 customWeapons.append(CustomWeapon(viewmodel,worldmodel,scriptScope))
1584 if("OnInitialize" in scriptScope){
1585 scriptScope["OnInitialize"]()
1586 }
1587 PrintInfo("Registered custom weapon script " + script)
1588 return scriptScope
1589 } else {
1590 PrintInvalidVarType(errorMessage, "script", VariableTypes.STRING, typeof(script))
1591 }
1592 } else {
1593 PrintInvalidVarType(errorMessage, "worldmodel", VariableTypes.STRING, typeof(worldmodel))
1594 }
1595 } else {
1596 PrintInvalidVarType(errorMessage, "viewmodel", VariableTypes.STRING, typeof(viewmodel))
1597 }
1598 return false
1599}
1600
1601/**
1602 * Registers various hooks
1603 */
1604function RegisterHooks(scriptScope){ //basically listens for keypresses and calls hooks
1605 if(CheckType(scriptScope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1606 hookScripts.append(scriptScope)
1607 PrintInfo("Successfully registered hooks")
1608 return true
1609 } else {
1610 PrintInvalidVarType("Failed to register hooks", "scriptScope", VariableTypes.TABLE, typeof(scriptScope))
1611 }
1612 return false
1613}
1614
1615/**
1616 * Registers a function to be called every tick in scriptScope
1617 */
1618function RegisterOnTick(scriptScope){
1619 if(CheckType(scriptScope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1620 tickScripts.append(scriptScope)
1621 PrintInfo("Registered OnTick")
1622 return true
1623 } else {
1624 PrintInvalidVarType("Failed to register OnTick", "scriptScope", VariableTypes.TABLE, typeof(scriptScope))
1625 }
1626 return false
1627}
1628
1629/**
1630 * Registers a function to be called every tick
1631 */
1632function RegisterTickFunction(func){
1633 if(CheckType(func, VariableTypes.FUNCTION)){
1634 tickFunctions.append(func)
1635 PrintInfo("Registered tick function")
1636 return true
1637 } else {
1638 PrintInvalidVarType("Failed to register a tick function", "func", VariableTypes.FUNCTION, typeof(func))
1639 }
1640 return false
1641}
1642
1643/**
1644 * Registers a function to be called when an entity is created
1645 */
1646function RegisterEntityCreateListener(classname, scope){
1647 local errorMessage = "Failed to register entity create listener"
1648 if(CheckType(classname, VariableTypes.STRING)){
1649 if(CheckType(scope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1650 entityCreateListeners.append(EntityCreateListener(classname,scope))
1651 PrintInfo("Registered entity create listener on " + classname + " entities")
1652 return true
1653 } else {
1654 PrintInvalidVarType(errorMessage, "scope", VariableTypes.STRING, typeof(scope))
1655 }
1656 } else {
1657 PrintInvalidVarType(errorMessage, "classname", VariableTypes.STRING, typeof(classname))
1658 }
1659 return false
1660}
1661
1662/**
1663 * Registers a function to be called when an entity moves
1664 */
1665function RegisterEntityMoveListener(ent, scope){
1666 local errorMessage = "Failed to register entity move listener"
1667 if(CheckType(ent, VariableTypes.INSTANCE)){
1668 if(CheckType(scope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1669 entityMoveListeners.append(EntityMoveListener(ent, scope))
1670 PrintInfo("Registered entity move listener on " + ent)
1671 return true
1672 } else {
1673 PrintInvalidVarType(errorMessage, "scope", VariableTypes.TABLE, typeof(scope))
1674 }
1675 } else {
1676 PrintInvalidVarType(errorMessage, "ent", VariableTypes.INSTANCE, typeof(ent))
1677 }
1678 return false
1679}
1680
1681/**
1682 * Registers a timer to be updated on the HUD
1683 */
1684function RegisterTimer(hudField, time, callFunction, countDown = true, formatTime = false){
1685 local errorMessage = "Failed to register timer"
1686 if(CheckType(hudField, VariableTypes.TABLE)){
1687 if(CheckType(time, VariableTypes.INTEGER) || CheckType(time, VariableTypes.FLOAT)){
1688 if(CheckType(callFunction, VariableTypes.FUNCTION)){
1689 if(CheckType(countDown, VariableTypes.BOOLEAN)){
1690 if(CheckType(formatTime, VariableTypes.BOOLEAN)){
1691 timers.append(Timer(hudField, time, callFunction, countDown, formatTime))
1692 PrintInfo("Registered hud timer")
1693 return true
1694 } else {
1695 PrintInvalidVarType(errorMessage, "formatTime", VariableTypes.BOOLEAN, typeof(formatTime))
1696 }
1697 } else {
1698 PrintInvalidVarType(errorMessage, "countDown", VariableTypes.BOOLEAN, typeof(countDown))
1699 }
1700 } else {
1701 PrintInvalidVarType(errorMessage, "callFunction", VariableTypes.FUNCTION, typeof(callFunction))
1702 }
1703 } else {
1704 PrintInvalidVarType(errorMessage, "time", VariableTypes.FLOAT, typeof(time))
1705 }
1706 } else {
1707 PrintInvalidVarType(errorMessage, "hudField", VariableTypes.TABLE, typeof(hudField))
1708 }
1709 return false
1710}
1711
1712/**
1713 * Stops a registered timer
1714 */
1715function StopTimer(hudField){
1716 if(CheckType(hudField, VariableTypes.TABLE)){
1717 for(local i=0; i < timers.len(); i++){
1718 if(timers[i].GetHudField() == hudField){
1719 timers.remove(i)
1720 PrintInfo("Stopped timer")
1721 return true
1722 }
1723 }
1724 PrintInfo("Timer already stopped")
1725 return false
1726 } else {
1727 PrintInvalidVarType(errorMessage, "hudField", VariableTypes.TABLE, typeof(hudField))
1728 }
1729 return false
1730}
1731
1732/**
1733 * Schedules a function to be called later
1734 */
1735function ScheduleTask(func, time, args = {}){ // can only check every 33 milliseconds so be careful
1736 local errorMessage = "Failed to schedule task"
1737 if(CheckType(func, VariableTypes.FUNCTION)){
1738 if(CheckType(time, VariableTypes.INTEGER) || CheckType(time, VariableTypes.FLOAT)){
1739 if(CheckType(args, VariableTypes.TABLE)){
1740 if(time > 0){
1741 tasks.append(Task(func, args, Time() + time))
1742 PrintInfo("Registered a task to execute at " + (Time()+time))
1743 return true
1744 } else {
1745 PrintError("Failed to register task (Time has to be greater than 0)")
1746 return false
1747 }
1748 } else {
1749 PrintInvalidVarType(errorMessage, "args", VariableTypes.TABLE, typeof(args))
1750 }
1751 } else {
1752 PrintInvalidVarType(errorMessage, "time", VariableTypes.FLOAT, typeof(time))
1753 }
1754 } else {
1755 PrintInvalidVarType(errorMessage, "func", VariableTypes.FUNCTION, typeof(func))
1756 }
1757 return false
1758}
1759
1760/**
1761 * Schedules a function to be called next tick
1762 */
1763function DoNextTick(func, args = {}){
1764 if(CheckType(func, VariableTypes.FUNCTION)){
1765 if(CheckType(args, VariableTypes.TABLE)){
1766 tasks.append(Task(func, args, Time() + 0.033))
1767 PrintInfo("Registered a task to execute next tick")
1768 return true
1769 } else {
1770 PrintInvalidVarType(errorMessage, "args", VariableTypes.TABLE, typeof(args))
1771 }
1772 } else {
1773 PrintInvalidVarType(errorMessage, "func", VariableTypes.FUNCTION, typeof(func))
1774 }
1775 return false
1776}
1777
1778/**
1779 * Registers a function to be called when a command is typed in chat
1780 */
1781function RegisterChatCommand(command, func, isInputCommand = false){
1782 local errorMessage = "Failed to register chat command"
1783 if(CheckType(command, VariableTypes.STRING)){
1784 if(CheckType(func, VariableTypes.FUNCTION)){
1785 if(CheckType(isInputCommand, VariableTypes.BOOLEAN)){
1786 chatCommands.append(ChatCommand(command, func, isInputCommand))
1787 PrintInfo("Registered chat command (isInput=" + isInputCommand + ", command=" + command + ")")
1788 return true
1789 } else {
1790 PrintInvalidVarType(errorMessage, "isInputCommand", VariableTypes.BOOLEAN, typeof(isInputCommand))
1791 }
1792 } else {
1793 PrintInvalidVarType(errorMessage, "func", VariableTypes.FUNCTION, typeof(func))
1794 }
1795 } else {
1796 PrintInvalidVarType(errorMessage, "command", VariableTypes.STRING, typeof(command))
1797 }
1798 return false
1799}
1800
1801/**
1802 * Registers a function to be called when a convar is changed
1803 */
1804function RegisterConvarListener(convar, convarType, scope){
1805 local errorMessage = "Failed to register convar listener"
1806 if(CheckType(convar, VariableTypes.STRING)){
1807 if(CheckType(convarType, VariableTypes.STRING)){
1808 if(CheckType(scope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1809 convarListeners.append(ConvarListener(convar, convarType, scope))
1810 PrintInfo("Registered convar listener")
1811 return true
1812 } else {
1813 PrintInvalidVarType(errorMessage, "scope", VariableTypes.TABLE, typeof(scope))
1814 }
1815 } else {
1816 PrintInvalidVarType(errorMessage, "convarType", VariableTypes.STRING, typeof(convarType))
1817 }
1818 } else {
1819 PrintInvalidVarType(errorMessage, "convar", VariableTypes.STRING, typeof(convar))
1820 }
1821 return false
1822}
1823
1824/**
1825 * Registers a function to be called when a bile jar explodes on the ground
1826 */
1827function RegisterBileExplodeListener(scope){
1828 if(CheckType(scope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1829 bileExplodeListeners.append(ThrowableExplodeListener(scope))
1830 PrintInfo("Registered a bile explode listener")
1831 return true
1832 } else {
1833 PrintInvalidVarType("Failed to register bile explode listener", "scope", VariableTypes.TABLE, typeof(scope))
1834 }
1835 return false
1836}
1837
1838/**
1839 * Registers a function to be called when a molotov explodes on the ground
1840 */
1841function RegisterMolotovExplodeListener(scope){
1842 if(CheckType(scope, VariableTypes.TABLE) || CheckType(scriptScope, VariableTypes.INSTANCE)){
1843 molotovExplodeListeners.append(ThrowableExplodeListener(scope))
1844 PrintInfo("Registered a molotov explode listener")
1845 return true
1846 } else {
1847 PrintInvalidVarType("Failed to register molotov explode listener", "scope", VariableTypes.TABLE, typeof(scope))
1848 }
1849 return false
1850}
1851
1852/**
1853 * Locks an entity by constantly setting its position
1854 */
1855function LockEntity(entity){
1856 if(CheckType(entity, VariableTypes.INSTANCE)){
1857 lockedEntities.append(LockedEntity(entity, entity.GetAngles(), entity.GetOrigin))
1858 PrintInfo("Locked entity: " + entity)
1859 return true
1860 } else {
1861 PrintInvalidVarType("Failed to lock entity", "entity", VariableTypes.INSTANCE, typeof(entity))
1862 }
1863 return false
1864}
1865
1866/**
1867 * Unlocks a previously locked entity
1868 */
1869function UnlockEntity(entity){
1870 if(CheckType(entity, VariableTypes.INSTANCE)){
1871 for(local i=0; i < lockedEntities.len(); i++){
1872 if(lockedEntities[i] == entity){
1873 lockedEntities.remove(i)
1874 return true
1875 }
1876 }
1877 return true
1878 } else {
1879 PrintInvalidVarType("Failed to unlock entity", "entity", VariableTypes.INSTANCE, typeof(entity))
1880 }
1881 return false
1882}
1883
1884function SetTimescale(timescale){
1885 if(CheckType(timescale, VariableTypes.FLOAT) || CheckType(timescale, VariableTypes.INTEGER)){
1886 DoEntFire("!self", "AddOutput", "desiredTimescale " + timescale, 0, null, timescaleEnt)
1887 DoEntFire("!self", "Start", "", 0, null, timescaleEnt)
1888 } else {
1889 PrintInvalidVarType("Failed to set timescale", "timescale", VariableTypes.FLOAT, typeof(timescale))
1890 }
1891 return false
1892}
1893
1894
1895function PlayerGenerator(){
1896 local ent = null
1897 while(ent = Entities.FindByClassname(ent, "player")){
1898 yield ent
1899 }
1900}
1901
1902function EntitiesByClassname(classname){
1903 local ent = null
1904 while(ent = Entities.FindByClassname(ent, classname)){
1905 yield ent
1906 }
1907}
1908
1909function EntitiesByClassnameWithin(classname, origin, radius){
1910 local ent = null
1911 while(ent = Entities.FindByClassnameWithin(ent, classname, origin, radius)){
1912 yield ent
1913 }
1914}
1915
1916function EntitiesByModel(model){
1917 local ent = null
1918 while(ent = Entities.FindByModel(ent, model)){
1919 yield ent
1920 }
1921}
1922
1923function EntitiesByName(name){
1924 local ent = null
1925 while(ent = Entities.FindByName(ent, name)){
1926 yield ent
1927 }
1928}
1929
1930function EntitiesByNameWithin(name, origin, radius){
1931 local ent = null
1932 while(ent = Entities.FindByNameWithin(ent, name, origin, radius)){
1933 yield ent
1934 }
1935}
1936
1937function EntitiesByTarget(targetname){
1938 local ent = null
1939 while(ent = Entities.FindByTarget(ent, targetname)){
1940 yield ent
1941 }
1942}
1943
1944function EntitiesInSphere(origin, radius){
1945 local ent = null
1946 while(ent = Entities.FindInSphere(ent, origin, radius)){
1947 yield ent
1948 }
1949}
1950
1951function EntitiesByOrder(){
1952 local ent = null
1953 while(ent = Entities.Next(ent)){
1954 yield ent
1955 }
1956}
1957
1958/*
1959function OnGameEvent_tongue_grab(params){
1960 PlayerRestricted(params.victim)
1961}
1962function OnGameEvent_choke_start(params){
1963 PlayerRestricted(params.victim)
1964}
1965function OnGameEvent_lunge_pounce(params){
1966 PlayerRestricted(params.victim)
1967}
1968function OnGameEvent_charger_carry_start(params){
1969 PlayerRestricted(params.victim)
1970}
1971function OnGameEvent_charger_pummel_start(params){
1972 PlayerRestricted(params.victim)
1973}
1974function OnGameEvent_jockey_ride(params){
1975 PlayerRestricted(params.victim)
1976}
1977
1978function OnGameEvent_tongue_release(params){
1979 if("victim" in params)
1980 {
1981 PlayerReleased(params.victim)
1982 }
1983}
1984function OnGameEvent_choke_end(params){
1985 if("victim" in params)
1986 {
1987 PlayerReleased(params.victim)
1988 }
1989}
1990function OnGameEvent_pounce_end(params){
1991 if("victim" in params)
1992 {
1993 PlayerReleased(params.victim)
1994 }
1995}
1996function OnGameEvent_pounce_stopped(params){
1997 if("victim" in params)
1998 {
1999 PlayerReleased(params.victim)
2000 }
2001}
2002function OnGameEvent_charger_carry_end(params){
2003 if("victim" in params)
2004 {
2005 PlayerReleased(params.victim)
2006 }
2007}
2008function OnGameEvent_charger_pummel_end(params){
2009 if("victim" in params)
2010 {
2011 PlayerReleased(params.victim)
2012 }
2013}
2014function OnGameEvent_jockey_ride_end(params){
2015 if("victim" in params)
2016 {
2017 PlayerReleased(params.victim)
2018 }
2019}
2020function PlayerRestricted(playerId){
2021 local player = FindPlayerObject(GetPlayerFromUserID(playerId))
2022 if(player != null){
2023 player.SetDisabled(true)
2024 }
2025}
2026function PlayerReleased(playerId){
2027 local player = FindPlayerObject(GetPlayerFromUserID(playerId))
2028 if(player != null){
2029 player.SetDisabled(false)
2030 }
2031}
2032*/
2033
2034/**
2035 * Returns true if the message matches the specified command
2036 */
2037local function IsCommand(msg, command){
2038 local message = ""
2039 local found_start = false
2040 local found_end = false
2041 local last_char = 0
2042 foreach(char in msg){
2043 if(char != CHAR_SPACE && char != CHAR_NEWLINE){
2044 if(!found_start){
2045 found_start = true
2046 }
2047 message += char.tochar()
2048 } else if(char == CHAR_SPACE){
2049 if(last_char != CHAR_SPACE){
2050 found_end = true
2051 }
2052 if(found_start && !found_end){
2053 message += char.tochar()
2054 }
2055 }
2056 }
2057 return message == command
2058}
2059
2060/**
2061 * Returns input if the message matches the command, otherwise returns false
2062 */
2063local function GetInputCommand(msg, command){
2064 local message = ""
2065 local found_start = false
2066 local found_end = false
2067 local last_char = 0
2068 local index = 0
2069 foreach(char in msg){
2070 if(char != CHAR_SPACE && char != CHAR_NEWLINE){
2071 if(!found_start){
2072 found_start = true
2073 }
2074 message += char.tochar()
2075 } else if(char == CHAR_SPACE){
2076 if(last_char != CHAR_SPACE){
2077 found_end = true
2078 if(message != command || index == msg.len() - 1){
2079 return false
2080 }
2081 return msg.slice(index + 1, msg.len())
2082 }
2083 if(found_start && !found_end){
2084 message += char.tochar()
2085 }
2086 }
2087 index += 1
2088 }
2089 return false
2090}
2091
2092
2093function OnGameEvent_player_say(params){
2094 local text = params["text"]
2095 local ent = GetPlayerFromUserID(params["userid"])
2096
2097 foreach(command in chatCommands){
2098 if(command.IsInputCommand()){
2099 local input = GetInputCommand(text, command.GetCommand())
2100 if(input != false){
2101 command.CallFunction(ent, input)
2102 }
2103 } else {
2104 if(IsCommand(text, command.GetCommand())){
2105 command.CallFunction(ent)
2106 }
2107 }
2108 }
2109}
2110
2111__CollectEventCallbacks(this, "OnGameEvent_", "GameEventCallbacks", RegisterScriptGameEventListener)