· 8 years ago · Oct 14, 2017, 05:46 PM
1--[[
2Name: "init.lua".
3Product: "ivg (Roleplay)".
4--]]
5
6require("tmysql");
7require("timerx");
8
9-- Include the shared gamemode file.
10include("sh_init.lua");
11
12function AddDir(dir)
13 local list = file.FindDir("../"..dir.."/*")
14 for _, fdir in pairs(list) do
15 if (fdir != ".svn" and fdir != "scripts") then
16 AddDir(dir.."/"..fdir)
17 end
18 end
19
20 for k,v in pairs(file.Find("../"..dir.."/*")) do
21 local dir = string.gsub(dir, "gamemodes/invisionrp/content/", "")
22 resource.AddFile(dir.."/"..v)
23 end
24end
25
26AddDir("gamemodes/invisionrp/content")
27
28-- Add the Lua files that we need to send to the client.
29AddCSLuaFile("cl_init.lua");
30AddCSLuaFile("sh_init.lua");
31AddCSLuaFile("core/sh_configuration.lua");
32AddCSLuaFile("core/sh_enumerations.lua");
33AddCSLuaFile("core/scoreboard/admin_buttons.lua");
34AddCSLuaFile("core/scoreboard/player_frame.lua");
35AddCSLuaFile("core/scoreboard/player_infocard.lua");
36AddCSLuaFile("core/scoreboard/player_row.lua");
37AddCSLuaFile("core/scoreboard/scoreboard.lua");
38AddCSLuaFile("core/scoreboard/vote_button.lua");
39
40-- Add our red glow to the download list.
41resource.AddFile("materials/sprites/redglow8.vmt");
42
43-- Enable realistic fall damage for this gamemode.
44game.ConsoleCommand("mp_falldamage 1\n");
45game.ConsoleCommand("sbox_godmode 0\n");
46game.ConsoleCommand("sbox_plpldamage 0\n");
47
48-- Some useful ConVars that can be changed in game.
49CreateConVar("ivg_ooc", 1);
50
51-- Store the old hook.Call function.
52hookCall = hook.Call;
53
54-- Overwrite the hook.Call function.
55function hook.Call(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)
56 if (a == "PlayerSay") then d = string.Replace(d, "$q", "\""); end;
57
58 -- Call the original hook.Call function.
59 return hookCall(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z);
60end;
61
62-- A table that will hold entities that were there when the map started.
63GM.entities = {};
64
65-- Called when the server initializes.
66function GM:Initialize()
67 local host = ivg.configuration["MySQL Host"];
68 local username = ivg.configuration["MySQL Username"];
69 local password = ivg.configuration["MySQL Password"];
70 local database = ivg.configuration["MySQL Database"];
71
72 -- Initialize a connection to the MySQL database.
73 tmysql.initialize(host, username, password, database, 3306, 5, 5);
74
75 -- Call the base class function.
76 return self.BaseClass:Initialize();
77end;
78
79-- Called when a player switches their flashlight on or off.
80function GM:PlayerSwitchFlashlight(player, on)
81 if (player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
82 return false;
83 else
84 return true;
85 end;
86end;
87
88-- Called when a player attempts to use an entity.
89function GM:PlayerUse(player, entity)
90 if (player:GetNWBool("Tied", false)) then return end
91
92 if (player._KnockedOut) then
93 return false;
94 elseif (player.ivg._Arrested) then
95 if ( !player._NextNotify or player._NextNotify < CurTime() ) then
96 ivg.player.notify(player, "You cannot do that in this state!", 1);
97
98 -- Set their next notify so that they don't get spammed with the message.
99 player._NextNotify = CurTime() + 2;
100 end;
101
102 -- Return false because they are Arrested.
103 return false;
104 elseif (ivg.entity.isDoor(entity) or entity:GetClass() == "prop_dynamic") then
105 if ( hook.Call("PlayerCanUseDoor", GAMEMODE, player, entity) ) then
106 ivg.entity.openDoor(entity, 0);
107 end;
108 end;
109
110 -- Call the base class function.
111 return self.BaseClass:PlayerUse(player, entity);
112end;
113
114-- Called when a player's warrant has expired.
115function GM:PlayerWarrantExpired(player, class) end;
116
117-- Called when a player demotes another player.
118function GM:PlayerDemote(player, target, team) end;
119
120-- Called when a player knocks out another player.
121function GM:PlayerKnockOut(player, target) end;
122
123-- Called when a player wakes up another player.
124function GM:PlayerWakeUp(player, target) end;
125
126-- Called when a player arrests another player.
127function GM:Playerarrest(player, target) end;
128
129-- Called when a player unarrests another player.
130function GM:PlayerUnarrest(player, target) end;
131
132-- Called when a player warrants another player.
133function GM:PlayerWarrant(player, target, class) end;
134
135-- Called when a player unwarrants another player.
136function GM:PlayerUnwarrant(player, target) end;
137
138-- Called when a player attempts to own a door.
139function GM:PlayerCanOwnDoor(player, door) return true; end;
140
141-- Called when a player attempts to view a door.
142function GM:PlayerCanViewDoor(player, door) return true; end;
143
144-- Called when a player attempts to holster a weapon.
145function GM:PlayerCanHolster(player, weapon, silent) return true; end;
146
147-- Called when a player attempts to drop a weapon.
148function GM:PlayerCanDrop(player, weapon, silent, attacker) return true; end;
149
150-- Called when a player attempts to use an item.
151function GM:PlayerCanUseItem(player, item, silent) return true; end;
152
153-- Called when a player attempts to knock out a player.
154function GM:PlayerCanKnockOut(player, target) return true; end;
155
156-- Called when a player attempts to warrant a player.
157function GM:PlayerCanWarrant(player, target) return true; end;
158
159-- Called when a player attempts to wake up another player.
160function GM:PlayerCanWakeUp(player, target) return true; end;
161
162-- Called when a player attempts to ram a door.
163function GM:PlayerCanRamDoor(player, door, silent)
164 if ( ValidEntity(door._Owner) ) then
165 if (!door._Owner._Warranted and !door._Owner.ivg._Arrested and door._Owner != player) then
166 ivg.player.notify(player, "This player does not have a search warrant!", 1);
167
168 -- Return false because the player requires a warrant.
169 return false;
170 end;
171 end;
172
173 -- Return true because we can ram this door.
174 return true;
175end;
176
177-- Called when a player attempts to use a door.
178function GM:PlayerCanUseDoor(player, door)
179 if ( ValidEntity(door._Owner) ) then
180 if (!door._Owner._Warranted and door._Owner != player) then
181 return false;
182 end;
183 end;
184
185 -- Return true because we can use this door.
186 return true;
187end;
188
189-- Called when a player enters a vehicle.
190function GM:PlayerEnteredVehicle(player, vehicle, role)
191 timerx.Simple(FrameTime() * 0.5, function()
192 if ( ValidEntity(player) ) then player:SetCollisionGroup(COLLISION_GROUP_PLAYER); end;
193 end);
194end;
195
196-- Called when a player attempts to join a team.
197function GM:PlayerCanJoinTeam(player, team)
198 team = ivg.team.get(team);
199
200 -- Check if this is a valid team.
201 if (team) then
202 if (player._NextChangeTeam[team.index]) then
203 if ( player._NextChangeTeam[team.index] > CurTime() ) then
204 local seconds = math.floor( player._NextChangeTeam[team.index] - CurTime() );
205
206 -- Notify them that they cannot change to this team yet.
207 ivg.player.notify(player, "Wait "..seconds.." second(s) to become a "..team.name.."!", 1);
208
209 -- Return here because they can't become this team.
210 return false;
211 end;
212 end;
213 end;
214
215 -- Check if the player is warranted.
216 if (player._Warranted) then
217 ivg.player.notify(player, "You cannot do that while you are warranted!", 1);
218
219 -- Return here because they can't become this team.
220 return false;
221 end;
222
223 -- Check if the player is knocked out.
224 if (player._KnockedOut) then
225 ivg.player.notify(player, "You cannot do that in this state!", 1);
226
227 -- Return here because they can't become this team.
228 return false;
229 end;
230
231 -- Return true because they can join this team.
232 return true;
233end;
234
235-- Called when a player earns contraband money.
236function GM:PlayerCanEarnContraband(player) return true; end;
237
238-- Called when a player attempts to unwarrant a player.
239function GM:PlayerCanUnwarrant(player, target)
240 if ( !player:IsAdmin() ) then
241 return true;
242 else
243 ivg.player.notify(player, "You do not have access to unwarrant this player!", 1);
244
245 -- Return false because they cannot unwarrant this player.
246 return false;
247 end;
248end;
249
250
251-- Called when a player attempts to demote another player.
252function GM:PlayerCanDemote(player, target)
253 if ( !player:IsAdmin() ) then
254 ivg.player.notify(player, "You do not have access to demote this player!", 1);
255
256 -- Return false because they cannot demote this player.
257 return false;
258 else
259 return true;
260 end;
261end;
262
263-- Called when all of the map entities have been initialized.a
264function GM:InitPostEntity()
265 timerx.Simple(2, function() for k, v in pairs( ents.GetAll() ) do self.entities[v] = v; end; end)
266
267 -- Call the base class function.
268 return self.BaseClass:InitPostEntity();
269end;
270
271-- Called when a player attempts to say something in-character.
272function GM:PlayerCanSayIC(player, text)
273 if (!player:Alive() or player._KnockedOut) then
274 ivg.player.notify(player, "You cannot talk in this state!", 1);
275
276 -- Return false because we can't say anything.
277 return false;
278 else
279 return true;
280 end;
281end;
282
283-- Called when a player attempts to say something in OOC.
284function GM:PlayerCanSayOOC(player, text)
285 if (player:IsAdmin() or GetConVarNumber("ivg_ooc") == 1) then
286 return true;
287 else
288 ivg.player.notify(player, "Talking in OOC has been disabled, if you talk OOC in advert you'll be permabanned!", 1);
289
290 -- Return false because we cannot talk out-of-character.
291 return false;
292 end;
293end;
294
295-- Called when a player attempts to say something in local OOC.
296function GM:PlayerCanSayLOOC(player, text) return true; end;
297
298-- Called when attempts to use a command.
299function GM:PlayerCanUseCommand(player, command, arguments)
300 if (command == "sleep" and player:Alive() and !player.ivg._Arrested and player._Sleeping) then
301 return true;
302 else
303 if (!player:Alive() or player._KnockedOut or player.ivg._Arrested or player:GetNWBool("Tied", false)) then
304 ivg.player.notify(player, "You cannot do that in this state!", 1);
305
306 -- Return false because we can't say anything.
307 return false;
308 else
309 return true;
310 end;
311 end;
312end;
313
314-- Called when a player says something.
315function GM:PlayerSay(player, text, public)
316 text = string.Replace(text, " ' ", "'");
317 text = string.Replace(text, " : ", ":");
318
319 -- Check if we're speaking on OOC.
320 if (string.sub(text, 1, 2) == "//") then
321 if (string.Trim( string.sub(text, 3) ) != "") then
322 if ( hook.Call("PlayerCanSayOOC", GAMEMODE, player, text) ) then
323 ivg.chatBox.add( nil, player, "ooc", string.Trim( string.sub(text, 3) ) );
324 end;
325 end;
326 elseif (string.sub(text, 1, 3) == ".//") then
327 if (string.Trim( string.sub(text, 4) ) != "") then
328 if ( hook.Call("PlayerCanSayLOOC", GAMEMODE, player, text) ) then
329 ivg.chatBox.addInRadius(player, "looc", string.Trim( string.sub(text, 4) ), player:GetPos(), ivg.configuration["Talk Radius"]);
330 end;
331 end;
332 else
333 if ( string.sub(text, 1, 1) == ivg.configuration["Command Prefix"] ) then
334 local arguments = string.Explode(" ", text);
335
336 -- Get the command from the arguments.
337 local command = string.sub(arguments[1], string.len(ivg.configuration["Command Prefix"]) + 1);
338 local quote = false;
339
340 -- Loop through the arguments that we specified.
341 for k, v in pairs(arguments) do
342 if (!quote and string.sub(v, 1, 1) == '"') then quote = true; end
343
344 -- Check if the key is greater than 1 so that we don't affect the command.
345 if (k > 1) then if (!quote) then arguments[k] = "\""..arguments[k].."\""; end; end;
346
347 -- Check if we are quoting and the last character is a quote.
348 if (quote and string.sub(v, -1) == '"') then quote = false; end;
349 end;
350
351 -- Run the console command on the player so that we can handle quoted arguments.
352 player:ConCommand("ivg "..command.." "..table.concat(arguments, " ", 2).."\n");
353 else
354 if ( hook.Call("PlayerCanSayIC", GAMEMODE, player, text) ) then
355 if (player.ivg._Arrested) then
356 ivg.chatBox.addInRadius(player, "Arrested", text, player:GetPos(), ivg.configuration["Talk Radius"]);
357 else
358 ivg.chatBox.addInRadius(player, "ic", text, player:GetPos(), ivg.configuration["Talk Radius"]);
359 end;
360 end;
361 end;
362 end;
363
364 -- Return an empty string so the text doesn't show.
365 return "";
366end;
367
368-- Called when a player attempts suicide.
369function GM:CanPlayerSuicide(player) return false; end;
370
371-- Called when a player attempts to punt an entity with the gravity gun.
372function GM:GravGunPunt(player, entity) DropEntityIfHeld(entity) return false; end;
373
374-- Called when a player attempts to pick up an entity with the physics gun.
375function GM:PhysgunPickup(player, entity)
376 if (self.entities[entity]) then return false; end;
377
378 if (entity.Added) then
379 return false;
380 end
381
382 if (entity:GetClass() == "prop_vehicle_prisoner_pod") then return false end
383
384 -- Check if the player is an administrator.
385 if ( player:IsAdmin() ) then
386 if (entity:GetClass() == "prop_vehicle_prisoner_pod") then return false end
387
388 if ( entity:IsPlayer() ) then
389 if ( !entity:InVehicle() ) then
390 entity:SetMoveType(MOVETYPE_NOCLIP);
391 else
392 return false;
393 end;
394 end;
395
396 -- Return true because administrators can pickup any entity.
397 return true;
398 end;
399
400 if (entity:GetClass() == "prop_vehicle_jeep") then return false end
401
402 -- Check if this entity is a player's ragdoll.
403 if ( ValidEntity(entity._Player) ) then return false; end;
404
405 -- Check if the entity is a forbidden class.
406 if ( string.find(entity:GetClass(), "npc_")
407 or string.find(entity:GetClass(), "ivg_")
408 or string.find(entity:GetClass(), "prop_dynamic")
409 or string.find(entity:GetClass(), "prop_class_vehicle")
410 or string.find(entity:GetClass(), "prop_vehicle_jeep")
411 or string.find(entity:GetClass(), "prop_vehicle_prisoner_pod")) then
412 return false;
413 end;
414
415 -- Call the base class function.
416 return self.BaseClass:PhysgunPickup(player, entity);
417end;
418
419-- Called when a player attempts to drop an entity with the physics gun.
420function GM:PhysgunDrop(player, entity)
421 if ( entity:IsPlayer() ) then entity:SetMoveType(MOVETYPE_WALK); end;
422end;
423
424-- Called when a player attempts to arrest another player.
425function GM:PlayerCanarrest(player, target)
426 if (target._Warranted == "arrest") then
427 return true;
428 else
429 ivg.player.notify(player, target:Name().." does not have an arrest warrant!", 1);
430
431 -- Return false because the target does not have a warrant.
432 return false;
433 end;
434end;
435
436-- Called when a player attempts to unarrest a player.
437function GM:PlayerCanUnarrest(player, target)
438 if ( !player:IsAdmin() ) then
439 return true;
440 else
441 ivg.player.notify(player, "You do not have access to unarrest this player!", 1);
442
443 -- Return false because we cannot unarrest this player.
444 return false;
445 end;
446end;
447
448-- Called when a player attempts to spawn an NPC.
449function GM:PlayerSpawnNPC(player, model)
450 if (!player:Alive() or player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
451 ivg.player.notify(player, "You cannot do that in this state!", 1);
452
453 -- Return false because we cannot spawn it.
454 return false;
455 end;
456
457 -- Check if the player is an administrator.
458 if ( !player:IsAdmin() ) then
459 return false;
460 else
461 return true;
462 end;
463end;
464
465-- Called when a player attempts to spawn a prop.
466function GM:PlayerSpawnProp(player, model)
467 if ( !ivg.player.hasAccess(player, "e") ) then return false; end;
468
469 -- Check if the player can spawn this prop.
470 if (!player:Alive() or player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
471 ivg.player.notify(player, "You cannot do that in this state!", 1);
472
473 -- Return false because we cannot spawn it.
474 return false;
475 end;
476
477 -- Check if the player is an administrator.
478 if ( player:IsAdmin() ) then return true; end;
479
480 -- Escape the bad characters from the model.
481 model = string.Replace(model, "\\", "/");
482 model = string.Replace(model, "//", "/");
483
484 -- Loop through our banned props to see if this one is banned.
485 for k, v in pairs(ivg.configuration["Banned Props"]) do
486 if ( string.lower(v) == string.lower(model) ) then
487 ivg.player.notify(player, "You cannot spawn banned props!", 1);
488
489 -- Return false because we cannot spawn it.
490 return false;
491 end;
492 end;
493
494 -- Check if they can spawn this prop yet.
495 if ( player._NextSpawnProp and player._NextSpawnProp > CurTime() ) then
496 ivg.player.notify(player, "You cannot spawn another prop for "..math.ceil( player._NextSpawnProp - CurTime() ).." second(s)!", 1);
497
498 -- Return false because we cannot spawn it.
499 return false;
500 else
501 player._NextSpawnProp = CurTime() + 1;
502 end;
503
504 -- Call the base class function.
505 return self.BaseClass:PlayerSpawnProp(player, model);
506end;
507
508-- Called when a player attempts to spawn a ragdoll.
509function GM:PlayerSpawnRagdoll(player, model)
510 if (!player:Alive() or player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
511 ivg.player.notify(player, "You cannot do that in this state!", 1);
512
513 -- Return false because we cannot spawn it.
514 return false;
515 end;
516
517 -- Check if the player is an administrator.
518 if ( !player:IsAdmin() ) then
519 return false;
520 else
521 return true;
522 end;
523end;
524
525-- Called when a player attempts to spawn an effect.
526function GM:PlayerSpawnEffect(player, model)
527 if (!player:Alive() or player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
528 ivg.player.notify(player, "You cannot do that in this state!", 1);
529
530 -- Return false because we cannot spawn it.
531 return false;
532 end;
533
534 -- Check if the player is an administrator.
535 if ( !player:IsAdmin() ) then
536 return false;
537 else
538 return true;
539 end;
540end;
541
542-- Called when a player attempts to spawn a vehicle.
543function GM:PlayerSpawnVehicle(player, model)
544 if ( !ivg.player.hasAccess(player, "e") ) then return false; end;
545
546 -- Check if the model is a chair.
547 if ( !string.find(model, "chair") and !string.find(model, "seat") ) then
548 return false;
549 end;
550
551 -- Check if the player can spawn this vehicle.
552 if (!player:Alive() or player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
553 ivg.player.notify(player, "You cannot do that in this state!", 1);
554
555 -- Return false because we cannot spawn it.
556 return false;
557 end;
558
559 -- Check if the player is an administrator.
560 if ( player:IsAdmin() ) then return true; end;
561
562 -- Call the base class function.
563 return self.BaseClass:PlayerSpawnVehicle(player, model);
564end;
565
566-- A function to check whether we're running on a listen server.
567function GM:IsListenServer()
568 for k, v in pairs( g_Player.GetAll() ) do
569 if ( v:IsListenServerHost() ) then return true; end;
570 end;
571
572 -- Check if we're running on single player.
573 if ( SinglePlayer() ) then return true; end;
574
575 -- Return false because there is no listen server host and it isn't single player.
576 return false;
577end;
578
579-- Called when a player attempts to use a tool.
580function GM:CanTool(player, trace, tool)
581 if ( player:IsAdmin() ) then return true; end;
582
583 -- Check if the trace entity is valid.
584 if ( ValidEntity(trace.Entity) ) then
585 if (tool == "nail") then
586 local line = {};
587
588 -- Set the information for the trace line.
589 line.start = trace.HitPos;
590 line.endpos = trace.HitPos + player:GetAimVector() * 16;
591 line.filter = {player, trace.Entity};
592
593 -- Perform the trace line.
594 line = util.TraceLine(line);
595
596 -- Check if the trace entity is valid.
597 if ( ValidEntity(line.Entity) ) then
598 if (self.entities[line.Entity]) then return false; end;
599 end;
600 end
601
602 -- Check if we're using the remover tool and we're trying to remove constrained entities.
603 if ( tool == "remover" and player:KeyDown(IN_ATTACK2) and !player:KeyDownLast(IN_ATTACK2) ) then
604 local entities = constraint.GetAllConstrainedEntities(trace.Entity);
605
606 -- Loop through the constained entities.
607 for k, v in pairs(entities) do
608 if (self.entities[v]) then return false; end;
609 end
610 end
611
612 -- Check if this entity cannot be used by the tool.
613 if (self.entities[trace.Entity]) then return false; end;
614
615 -- Check if this entity is a player's ragdoll.
616 if ( ValidEntity(trace.Entity._Player) ) then return false; end;
617 end;
618
619 -- Call the base class function.
620 return self.BaseClass:CanTool(player, trace, tool);
621end;
622
623-- Called when a player attempts to noclip.
624function GM:PlayerNoClip(player)
625 if (player.ivg._Arrested or player._KnockedOut or player:GetNWBool("Tied", false)) then
626 return false;
627 else
628 if ( player:IsAdmin() ) then
629 return true;
630 else
631 return false;
632 end;
633 end;
634end;
635
636-- Called when the player has initialized.
637function GM:PlayerInitialized(player)
638 local uniqueID = player:UniqueID();
639
640 -- Create a timer to give this player their salary.
641 timerx.Create("Give Salary: "..uniqueID, ivg.configuration["Salary Interval"], 0, function()
642 if ( ValidEntity(player) ) then
643 if (player:Alive() and !player.ivg._Arrested) then
644 ivg.player.giveMoney(player, player._Salary);
645
646 -- Print a message to the player letting them know they received their salary.
647 ivg.player.notify(player, "You received $"..player._Salary.." salary.", 0);
648 end;
649
650 -- Save the player's data.
651 ivg.player.saveData(player);
652 else
653 timerx.Stop("Give Salary: "..uniqueID);
654 end;
655 end);
656end;
657
658-- Called when a player's data is loaded.
659function GM:PlayerDataLoaded(player, success)
660 player._Job = ivg.configuration["Default Job"];
661 player._Ammo = {};
662 player._Gender = "Male";
663 player._Salary = 0;
664 player._Ragdoll = {};
665 player._Sleeping = false;
666 player._Warranted = false;
667 player._LightSpawn = false;
668 player._ScaleDamage = false;
669 player._Initialized = true;
670 player._ChangeTeam = false;
671 player._NextChangeTeam = {};
672 player._NextSpawnGender = "";
673 player._HideHealthEffects = false;
674 player._CannotBeWarranted = 0;
675
676 -- Some player variables based on configuration.
677 player._SpawnTime = ivg.configuration["Spawn Time"];
678 player._arrestTime = ivg.configuration["arrest Time"];
679 player._KnockOutTime = ivg.configuration["Knock Out Time"];
680
681 -- Call a hook for the gamemode.
682 hook.Call("PlayerInitialized", GAMEMODE, player);
683
684 -- ivgpawn them now that they have initialized and then freeze them.
685 player:Spawn();
686 player:Freeze(true);
687
688 -- Unfreeze them in a few seconds from now.
689 timerx.Simple(2, function()
690 if ( ValidEntity(player) ) then
691 player:Freeze(false);
692
693 -- We can now start updating the player's data.
694 player._UpdateData = true;
695
696 -- Send a user message to remove the loading screen.
697 umsg.Start("ivg.player.initialized", player); umsg.End();
698 end;
699 end);
700
701 -- Check if the player is Arrested.
702 if (player.ivg._Arrested) then ivg.player.arrest(player, true, true); end;
703end;
704
705-- Called when a player initially spawns.
706function GM:PlayerInitialSpawn(player)
707 if ( ValidEntity(player) ) then
708 ivg.player.loadData(player);
709
710 -- A table of valid door classes.
711 local doorClasses = {
712 "func_door",
713 "func_door_rotating",
714 "prop_door_rotating"
715 };
716
717 -- Loop through our table of valid door classes.
718 for k, v in pairs(doorClasses) do
719 for k2, v2 in pairs( ents.FindByClass(v) ) do
720 if ( ivg.entity.isDoor(v2) ) then
721 if (player:UniqueID() == v2._UniqueID) then
722 v2._Owner = player;
723
724 -- Set the networked owner so that the client can get it.
725 v2:SetNetworkedEntity("ivg_Owner", player);
726 end;
727 end;
728 end;
729 end;
730
731 -- A table to store every contraband entity.
732 local contraband = {};
733
734 -- Loop through each contraband class.
735 for k, v in pairs( ivg.configuration["Contraband"] ) do
736 table.Add( contraband, ents.FindByClass(k) );
737 end;
738
739 -- Loop through all of the contraband.
740 for k, v in pairs(contraband) do
741 if (player:UniqueID() == v._UniqueID) then v:SetPlayer(player); end;
742 end;
743
744 -- Kill them silently until we've loaded the data.
745 player:KillSilent();
746 end;
747end
748
749-- Called every frame that a player is dead.
750function GM:PlayerDeathThink(player)
751 if (!player._Initialized) then return true; end;
752
753 -- Check if the player is a bot.
754 if (player:SteamID() == "BOT") then
755 if (player.NextSpawnTime and CurTime() >= player.NextSpawnTime) then player:Spawn(); end;
756 end;
757
758 -- Return the base class function.
759 return self.BaseClass:PlayerDeathThink(player);
760end;
761
762-- Called when a player's salary should be adjusted.
763function GM:PlayerAdjustSalary(player) end;
764
765-- Called when a player's radio recipients should be adjusted.
766function GM:PlayerAdjustRadioRecipients(player, text, recipients) end;
767
768-- Called when a player should gain a frag.
769function GM:PlayerCanGainFrag(player, victim) return true; end;
770
771-- Called when a player's model should be set.
772function GM:PlayerSetModel(player)
773 local models = ivg.team.query(player:Team(), "models");
774
775 -- Check if the models table exists.
776 if (models) then
777 models = models[ string.lower(player._Gender) ];
778
779 -- Check if the models table exists for this gender.
780 if (models) then
781 local model = models[ math.random(1, #models) ];
782
783 -- Set the player's model to the we got.
784 player:SetModel(model);
785 end;
786 end;
787end;
788
789-- Called when a player spawns.
790function GM:PlayerSpawn(player)
791 if (player._Initialized) then
792 if (player._NextSpawnGender != "") then
793 player._Gender = player._NextSpawnGender; player._NextSpawnGender = "";
794 end;
795
796 -- Set it so that the player does not drop weapons.
797 player:ShouldDropWeapon(false);
798
799 -- Check if we're not doing a light spawn.
800 if (!player._LightSpawn) then
801 player:SetRunSpeed( ivg.configuration["Run Speed"] );
802 player:SetWalkSpeed( ivg.configuration["Walk Speed"] );
803
804 -- Set some of the player's variables.
805 player._Ammo = {};
806 player._Sleeping = false;
807 player._ScaleDamage = false;
808 player._HideHealthEffects = false;
809 player._CannotBeWarranted = CurTime() + 15;
810
811 -- Make the player become conscious again.
812 ivg.player.knockOut(player, false, nil, true);
813
814 -- Set the player's model and give them their loadout.
815 self:PlayerSetModel(player);
816 self:PlayerLoadout(player);
817 end;
818
819 -- Call a gamemode hook for when the player has finished spawning.
820 hook.Call("PostPlayerSpawn", GAMEMODE, player, player._LightSpawn, player._ChangeTeam);
821
822 -- Set some of the player's variables.
823 player._LightSpawn = false;
824 player._ChangeTeam = false;
825 else
826 player:KillSilent();
827 end;
828end;
829
830-- Called when a player should take damage.
831function GM:PlayerShouldTakeDamage(player, attacker) return true; end;
832
833-- Called when a player is attacked by a trace.
834function GM:PlayerTraceAttack(player, damageInfo, direction, trace)
835 player._LastHitGroup = trace.HitGroup;
836
837 -- Return false so that we don't override internals.
838 return false;
839end;
840
841-- Called just before a player dies.
842function GM:DoPlayerDeath(player, attacker, damageInfo)
843 if (player:GetNWBool("Tied", false)) then player:SetNWBool("Tied", false) end
844
845 for k, v in pairs( player:GetWeapons() ) do
846 local class = v:GetClass()
847
848 if (ivg.item.stored[class] and ivg.item.stored[class].primary) then
849 player._PrimaryWeapon = false
850 elseif (ivg.item.stored[class] and ivg.item.stored[class].secondary) then
851 player._SecondaryWeapon = (player._SecondaryWeapon or 1) - 1
852 end
853 end
854
855 if (player:Team() == TEAM_CITYADMINISTRATOR) then
856 for k,v in pairs(ents.FindByClass("prop_vehicle_jeep")) do
857 if (v.Government) then
858 if (v:GetNWString("ivg_Item", "") == "police_car" or v:GetNWString("ivg_Item", "") == "fire_truck") then
859 v:Remove()
860
861 ivg.GovernmentPoliceCars = 1
862 ivg.GovernmentFireTruck = 1
863 end
864 end
865 end
866 elseif (player:Team() == TEAM_SWATLEADER) then
867 for k,v in pairs(ents.FindByClass("prop_vehicle_jeep")) do
868 if (v.Government) then
869 if (v:GetNWString("ivg_Item", "") == "swat_vehicle") then
870 v:Remove()
871
872 ivg.GovernmentSwatVehicle = 1
873 end
874 end
875 end
876 end
877
878 -- Unwarrant them, unarrest them and stop them from bleeding.
879 ivg.player.warrant(player, false);
880 ivg.player.arrest(player, false, true);
881 ivg.player.bleed(player, false);
882
883 -- Strip the player's weapons and ammo.
884 player:StripWeapons();
885 player:StripAmmo();
886
887 -- Add a death to the player's death count.
888 player:AddDeaths(1);
889
890 -- Check it the attacker is a valid entity and is a player.
891 if ( ValidEntity(attacker) and attacker:IsPlayer() ) then
892 if (player != attacker) then
893 if ( hook.Call("PlayerCanGainFrag", GAMEMODE, attacker, player) ) then
894 attacker:AddFrags(1);
895 end;
896 end;
897 end;
898end;
899
900-- Called when a player dies.
901function GM:PlayerDeath(player, inflictor, attacker, ragdoll)
902 if (ragdoll != false) then
903 player._Ragdoll.weapons = {};
904 player._Ragdoll.health = player:Health();
905 player._Ragdoll.model = player:GetModel();
906 player._Ragdoll.team = player:Team();
907
908 -- Knockout the player to simulate their death.
909 ivg.player.knockOut(player, true);
910 end;
911
912 if (timerx.IsTimer("RegenHealth: "..player:UniqueID())) then timerx.Stop("RegenHealth: "..player:UniqueID()) end
913
914 -- Set their next spawn time.
915 player.NextSpawnTime = CurTime() + player._SpawnTime;
916
917 -- Set it so that we can the next spawn time client side.
918 ivg.player.setLocalPlayerVariable(player, CLASS_LONG, "_NextSpawnTime", player.NextSpawnTime);
919
920 -- Check if the attacker is a player.
921 if ( attacker:IsPlayer() ) then
922 if ( ValidEntity( attacker:GetActiveWeapon() ) ) then
923 ivg.player.printConsoleAccess(attacker:Name().." killed "..player:Name().." with "..attacker:GetActiveWeapon():GetClass()..".", "a");
924 else
925 ivg.player.printConsoleAccess(attacker:Name().." killed "..player:Name()..".", "a");
926 end;
927 else
928 ivg.player.printConsoleAccess(attacker:GetClass().." killed "..player:Name()..".", "a");
929 end;
930end;
931
932-- Called when a player's weapons should be given.
933function GM:PlayerLoadout(player)
934 if ( ivg.player.hasAccess(player, "t") ) then player:Give("gmod_tool"); end
935 if ( ivg.player.hasAccess(player, "p") ) then player:Give("weapon_physgun"); end
936
937 -- Give the player the camera, the hands and the physics cannon.
938 player:Give("gmod_camera");
939 player:Give("ivg_hands");
940 player:Give("weapon_physcannon");
941
942 -- Call the player loadout hook.
943 ivg.plugin.call("playerLoadout", player);
944
945 -- Select the hands by default.
946 player:SelectWeapon("ivg_hands");
947end
948
949-- Called when the server shuts down or the map changes.
950function GM:ShutDown()
951 for k, v in pairs( g_Player.GetAll() ) do
952 ivg.player.holsterAll(v2);
953
954 -- Save the player's data.
955 ivg.player.saveData(v);
956 end;
957end;
958
959-- Called when a player Presses F1.
960function GM:ShowHelp(player) umsg.Start("ivg_Menu", player); umsg.End(); end;
961
962-- Called when a player Presses F2.
963function GM:ShowTeam(player)
964 local door = player:GetEyeTrace().Entity;
965
966 -- Check if the player is aiming at a door.
967 if ( ValidEntity(door) and ivg.entity.isDoor(door) ) then
968 if (door:GetPos():Distance( player:GetPos() ) <= 128) then
969 if ( hook.Call("PlayerCanViewDoor", GAMEMODE, player, door) ) then
970 umsg.Start("ivg_Door", player);
971 umsg.Bool(door._Unsellable or false);
972
973 -- Check if the owner is a valid entity.
974 if ( ValidEntity(door._Owner) ) then
975 umsg.Entity(door._Owner);
976 else
977 umsg.Entity(NULL);
978 end;
979
980 -- Send the door as an entity and unsellable as a bool.
981 umsg.Entity(door);
982
983 -- Check if the door has access.
984 if (door._Access) then
985 for k, v in pairs( g_Player.GetAll() ) do
986 if (v != door._Owner) then
987 local uniqueID = v:UniqueID();
988
989 -- Check if they have access.
990 if (door._Access[uniqueID]) then
991 umsg.Short( v:EntIndex() );
992 umsg.Short(1);
993 else
994 umsg.Short( v:EntIndex() );
995 umsg.Short(0);
996 end;
997 end;
998 end;
999 end;
1000 umsg.End();
1001 end;
1002 end;
1003 end;
1004end;
1005
1006-- Called when an entity takes damage.
1007function GM:EntityTakeDamage(entity, inflictor, attacker, amount, damageInfo)
1008 if (attacker:IsPlayer() and ValidEntity( attacker:GetActiveWeapon() )
1009 and attacker:GetActiveWeapon():GetClass() == "weapon_stunstick") then
1010 damageInfo:SetDamage(10);
1011 elseif (attacker:IsPlayer() and ValidEntity( attacker:GetActiveWeapon() )
1012 and attacker:GetActiveWeapon():GetClass() == "ivg_hands") then
1013 damageInfo:ScaleDamage(1);
1014 end;
1015
1016 -- Check if the entity that got damaged is a player.
1017 if ( entity:IsPlayer() ) then
1018 if (entity._KnockedOut) then
1019 if ( ValidEntity(entity._Ragdoll.entity) ) then
1020 hook.Call("EntityTakeDamage", GAMEMODE, entity._Ragdoll.entity, inflictor, attacker, damageInfo:GetDamage(), damageInfo);
1021 end;
1022 else
1023 if ( entity:InVehicle() and damageInfo:IsExplosionDamage() ) then
1024 if (!damageInfo:GetDamage() or damageInfo:GetDamage() == 0) then
1025 damageInfo:SetDamage(100);
1026 end;
1027 end;
1028
1029 -- Check if the player has a last hit group defined.
1030 if (entity._LastHitGroup) then
1031 if (entity._LastHitGroup == HITGROUP_HEAD) then
1032 damageInfo:ScaleDamage( ivg.configuration["Scale Head Damage"] );
1033 elseif (entity._LastHitGroup == HITGROUP_CHEST or entity._LastHitGroup == HITGROUP_GENERIC) then
1034 damageInfo:ScaleDamage( ivg.configuration["Scale Chest Damage"] );
1035 elseif (entity._LastHitGroup == HITGROUP_LEFTARM or
1036 entity._LastHitGroup == HITGROUP_RIGHTARM or
1037 entity._LastHitGroup == HITGROUP_LEFTLEG or
1038 entity._LastHitGroup == HITGROUP_RIGHTLEG or
1039 entity._LastHitGroup == HITGROUP_GEAR) then
1040 damageInfo:ScaleDamage( ivg.configuration["Scale Limb Damage"] );
1041 end;
1042
1043 -- Set the last hit group to nil so that we don't use it again.
1044 entity._LastHitGroup = nil;
1045 end;
1046
1047 -- Check if the player is supposed to scale damage.
1048 if (entity._ScaleDamage) then damageInfo:ScaleDamage(entity._ScaleDamage); end;
1049
1050 -- Make the player bleed.
1051 ivg.player.bleed( entity, true, ivg.configuration["Bleed Time"] );
1052 end;
1053 elseif ( entity:IsNPC() ) then
1054 if (attacker:IsPlayer() and ValidEntity( attacker:GetActiveWeapon() )
1055 and attacker:GetActiveWeapon():GetClass() == "weapon_crowbar") then
1056 damageInfo:ScaleDamage(0.25);
1057 end;
1058 end;
1059
1060 -- Check if the entity is a knocked out player.
1061 if ( ValidEntity(entity._Player) ) then
1062 local player = entity._Player;
1063
1064 -- Set the damage to the amount we're given.
1065 damageInfo:SetDamage(amount);
1066
1067 -- Check if the attacker is not a player.
1068 if ( !attacker:IsPlayer() ) then
1069 if ( attacker == GetWorldEntity() ) then
1070 if ( ( entity._NextWorldDamage and entity._NextWorldDamage > CurTime() )
1071 or damageInfo:GetDamage() <= 10 ) then return; end;
1072
1073 -- Set the next world damage to be 1 second from now.
1074 entity._NextWorldDamage = CurTime() + 1;
1075 else
1076 if (damageInfo:GetDamage() <= 25) then return; end;
1077 end;
1078 else
1079 damageInfo:ScaleDamage( ivg.configuration["Scale Ragdoll Damage"] );
1080 end;
1081
1082 -- Check if the player is supposed to scale damage.
1083 if (entity._Player._ScaleDamage) then damageInfo:ScaleDamage(entity._Player._ScaleDamage); end;
1084
1085 -- Take the damage from the player's health.
1086 player:SetHealth( math.max(player:Health() - damageInfo:GetDamage(), 0) );
1087
1088 -- Set the player's conscious health.
1089 player._Ragdoll.health = player:Health();
1090
1091 -- Create new effect data so that we can create a blood impact at the damage position.
1092 local effectData = EffectData();
1093 effectData:SetOrigin( damageInfo:GetDamagePosition() );
1094 util.Effect("BloodImpact", effectData);
1095
1096 -- Loop from 1 to 4 so that we can draw some blood decals around the ragdoll.
1097 for i = 1, 2 do
1098 local trace = {};
1099
1100 -- Set some settings and information for the trace.
1101 trace.start = damageInfo:GetDamagePosition();
1102 trace.endpos = trace.start + (damageInfo:GetDamageForce() + (VectorRand() * 16) * 128);
1103 trace.filter = entity;
1104
1105 -- Create the trace line from the set information.
1106 trace = util.TraceLine(trace);
1107
1108 -- Draw a blood decal at the hit position.
1109 util.Decal("Blood", trace.HitPos + trace.HitNormal, trace.HitPos - trace.HitNormal);
1110 end;
1111
1112 -- Check to see if the player's health is less than 0 and that the player is alive.
1113 if ( player:Health() <= 0 and player:Alive() ) then
1114 player:KillSilent();
1115
1116 -- Call some gamemode hooks to fake the player's death.
1117 hook.Call("DoPlayerDeath", GAMEMODE, player, attacker, damageInfo);
1118 hook.Call("PlayerDeath", GAMEMODE, player, inflictor, attacker, false);
1119 end;
1120 end;
1121end;
1122
1123-- Called when a player has disconnected.
1124function GM:PlayerDisconnected(player)
1125 ivg.player.holsterAll(player);
1126 ivg.player.knockOut(player, false, nil, true);
1127
1128 if (timerx.IsTimer("RegenHealth: "..player:UniqueID())) then timerx.Stop("RegenHealth: "..player:UniqueID()) end
1129
1130 -- Save the player's data.
1131 ivg.player.saveData(player);
1132
1133 for k,v in pairs(ents.GetAll()) do
1134 if (v.Owner == player) then
1135 v:Remove()
1136 end
1137 end
1138
1139 -- Call the base class function.
1140 self.BaseClass:PlayerDisconnected(player);
1141end;
1142
1143-- Called when a player attempts to spawn a SWEP.
1144function GM:PlayerSpawnSWEP(player, class, weapon)
1145 return false;
1146end;
1147
1148-- Called when a player is given a SWEP.
1149function GM:PlayerGiveSWEP(player, class, weapon)
1150 return false;
1151end;
1152
1153-- Called when attempts to spawn a SENT.
1154function GM:PlayerSpawnSENT(player, class)
1155 return false;
1156end;
1157
1158-- Called when a player Presses a key.
1159function GM:KeyPress(player, key)
1160 if (key == IN_JUMP and player._StuckInWorld) then
1161 ivg.player.holsterAll(player);
1162
1163 -- Spawn them lightly now that we holstered their weapons.
1164 ivg.player.lightSpawn(player);
1165 end;
1166end;
1167
1168-- Create a timer to automatically clean up decals.
1169timerx.Create("Cleanup Decals", 60, 0, function()
1170 if ( ivg.configuration["Cleanup Decals"] ) then
1171 for k, v in pairs( g_Player.GetAll() ) do v:ConCommand("r_cleardecals\n"); end;
1172 end;
1173end);
1174
1175-- Create a timer to give players money for their contraband.
1176timer.Create("Contraband", ivg.configuration["Contraband Interval"], 0, function()
1177 local players = {};
1178 local contraband = {};
1179
1180 -- Loop through each contraband class.
1181 for k, v in pairs( ivg.configuration["Contraband"] ) do
1182 table.Add( contraband, ents.FindByClass(k) );
1183 end;
1184
1185 -- Loop through all of the contraband.
1186 for k, v in pairs(contraband) do
1187 local player = v:GetPlayer();
1188
1189 -- Check if the player is a valid entity,
1190 if ( ValidEntity(player) ) then
1191 players[player] = players[player] or {refill = 0, money = 0};
1192
1193 -- Decrease the energy of the contraband.
1194 v._Energy = math.Clamp(v._Energy - 1, 0, 5);
1195
1196 -- Set the networked variable so that the client can use it.
1197 v:SetNetworkedInt("ivg_Energy", v._Energy);
1198
1199 -- Check the energy of the contraband.
1200 if (v._Energy == 0) then
1201 players[player].refill = players[player].refill + 1;
1202 else
1203 players[player].money = players[player].money + ivg.configuration["Contraband"][ v:GetClass() ].money;
1204
1205 if( players[player].money > 0 )then
1206 -- Spawn the money
1207 local moneyEnt = ents.Create("ivg_money");
1208
1209 -- Set the amount and position of the money.
1210 moneyEnt:SetAmount(ivg.configuration["Contraband"][ v:GetClass() ].money);
1211 moneyEnt:SetPos( v:GetPos() + Vector(0, 0, 16 ) );
1212 moneyEnt:Spawn();
1213 end;
1214 end;
1215 end;
1216 end;
1217
1218-- Loop through our players list.
1219 for k, v in pairs(players) do
1220 if ( hook.Call("PlayerCanEarnContraband", GAMEMODE, k) ) then
1221 if (v.refill > 0) then
1222 ivg.player.notify(k, v.refill.." of your contraband need refilling!", 1);
1223 end;
1224 end;
1225end);
1226
1227
1228function GM:PlayerCanHearPlayersVoice(listener, talker)
1229 return (listener:GetPos():Distance(talker:GetPos()) <= 512)
1230end;
1231
1232hook.Add("Initialize", "ivg_Precache", function()
1233 for k,v in pairs(ivg.configuration["Male Citizen Models"]) do
1234 util.PrecacheModel(v)
1235 end
1236
1237 for k,v in pairs(ivg.configuration["Female Citizen Models"]) do
1238 util.PrecacheModel(v)
1239 end
1240
1241 for k,v in pairs(ivg.item.stored) do
1242 if (v.vehicle) then
1243 util.PrecacheModel(v.model)
1244 end
1245 end
1246end)