@@ -1,5 +1,5 @@
--[[
© 2013 CloudSixteen.com do not share, re-distribute or modify
© 2013 CloudSixteen.com do not share, re-distribute or modify
without permission of its author (kurozael@gmail.com).
--]]

@@ -28,7 +28,7 @@ end;
-- Called when a player's default model is needed.
function Schema:GetPlayerDefaultModel(player)
local faction = player:GetFaction();

if (self:IsCombineFaction(faction)) then
if (self:IsPlayerCombineRank(player, "GHOST")) then
return "models/eliteghostcp.mdl";
@@ -47,12 +47,12 @@ function Schema:EntityHandleMenuOption(player, entity, option, arguments)
if (entity:GetClass() == "prop_ragdoll" and arguments == "cw_corpseLoot") then
if (!entity.cwInventory) then entity.cwInventory = {}; end;
if (!entity.cash) then entity.cash = 0; end;

local entityPlayer = Clockwork.entity:GetPlayer(entity);

if (!entityPlayer or !entityPlayer:Alive()) then
player:EmitSound("physics/body/body_medium_impact_soft"..math.random(1, 7)..".wav");

Clockwork.storage:Open( player, {
name = "Corpse",
weight = 8,
@@ -70,7 +70,7 @@ function Schema:EntityHandleMenuOption(player, entity, option, arguments)
end;
elseif (entity:GetClass() == "cw_belongings" and arguments == "cw_belongingsOpen") then
player:EmitSound("physics/body/body_medium_impact_soft"..math.random(1, 7)..".wav");

Clockwork.storage:Open( player, {
name = "Belongings",
weight = 100,
@@ -103,14 +103,14 @@ function Schema:EntityHandleMenuOption(player, entity, option, arguments)
if (option == "Set Frequency" and type(arguments) == "string") then
if (string.find(arguments, "^%d%d%d%.%d$")) then
local start, finish, decimal = string.match(arguments, "(%d)%d(%d)%.(%d)");

start = tonumber(start);
finish = tonumber(finish);
decimal = tonumber(decimal);

if (start == 1 and finish > 0 and finish < 10 and decimal > 0 and decimal < 10) then
entity:SetFrequency(arguments);

Clockwork.player:Notify(player, "You have set this stationary radio's arguments to "..arguments..".");
else
Clockwork.player:Notify(player, "The radio arguments must be between 101.1 and 199.9!");
@@ -122,7 +122,7 @@ function Schema:EntityHandleMenuOption(player, entity, option, arguments)
entity:Toggle();
elseif (arguments == "cw_radioTake") then
local bSuccess, fault = player:GiveItem(Clockwork.item:CreateInstance("stationary_radio"));

if (!bSuccess) then
Clockwork.player:Notify(player, fault);
else
@@ -137,12 +137,12 @@ function Schema:OnNPCKilled(npc, attacker, inflictor)
for k, v in pairs(self.scanners) do
local scanner = v[1];
local player = k;

if (IsValid(player) and IsValid(scanner) and scanner == npc) then
Clockwork.kernel:CalculateSpawnTime(player, inflictor, attacker);

npc:EmitSound("npc/scanner/scanner_explode_crash2.wav");

self:PlayerDeath(player, inflictor, attacker, true);
self:ResetPlayerScanner(player);
end;
@@ -153,7 +153,7 @@ end;
function Schema:SetupPlayerVisibility(player)
if (self.scanners[player]) then
local scanner = self.scanners[player][1];

if (IsValid(scanner)) then
AddOriginToPVS( scanner:GetPos() );
end;
@@ -172,18 +172,18 @@ function Schema:PlayerAdjustDropWeaponInfo(player, info)
Clockwork.player:GetGear(player, "Primary"),
Clockwork.player:GetGear(player, "Melee")
};

for k, v in pairs(gearTable) do
if (IsValid(v)) then
local gearItemTable = v:GetItemTable();

if (gearItemTable and gearItemTable.weaponClass == info.itemTable.weaponClass) then
local position, angles = v:GetRealPosition();

if (position and angles) then
info.position = position;
info.angles = angles;

break;
end;
end;
@@ -196,11 +196,11 @@ end;
function Schema:PlayerUseDoor(player, door)
if (string.lower( game.GetMap() ) == "rp_c18_v1") then
local name = string.lower( door:GetName() );

if (name == "nxs_brnroom" or name == "nxs_brnroom2" or name == "Clockwork_al_door1"
or name == "Clockwork_al_door2" or name == "nxs_brnbcroom") then
local curTime = CurTime();

if (!door.nextAutoClose or curTime >= door.nextAutoClose) then
door:Fire("Close", "", 10);
door.nextAutoClose = curTime + 10;
@@ -218,68 +218,42 @@ end;

-- Called when a player's default inventory is needed.
function Schema:GetPlayerDefaultInventory(player, character, inventory)
if (character.faction == FACTION_ADMIN) then
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("handheld_radio")
);
end
elseif (character.faction == FACTION_MPF) then
if (character.faction == FACTION_MILITARY) then
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("handheld_radio")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("weapon_pistol")
inventory, Clockwork.item:CreateInstance("m9k_usp")
);
for i = 1, 2 do
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("ammo_pistol")
inventory, Clockwork.item:CreateInstance("m9k_ammo_pistol")
);
end;

end

elseif (character.faction == FACTION_OTA) then
elseif (character.faction == FACTION_GOVT) then
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("handheld_radio")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("weapon_pistol")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("ammo_pistol")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("weapon_ar2")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("ammo_ar2")
);
end
elseif (character.faction == FACTION_GOVT) then
for i = 1, 2 do
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("med_rags")
);
end;
elseif (character.faction == FACTION_CIVILIAN) then
for i = 1, 2 do
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("med_rags")
);
else
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("med_rags")
);
end;
else
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("med_rags")
);
Clockwork.inventory:AddInstance(
inventory, Clockwork.item:CreateInstance("med_rags")
);
end;
end;

-- Called when a player's typing display has started.
function Schema:PlayerStartTypingDisplay(player, code)
if (Schema:PlayerIsCombine(player) and !player:IsNoClipping()) then
if (code == "n" or code == "y" or code == "w" or code == "r") then
if (!player.typingBeep) then
player.typingBeep = true;

player:EmitSound("npc/overwatch/radiovoice/on1.wav");
end;
end;
@@ -293,33 +267,33 @@ function Schema:PlayerFinishTypingDisplay(player, textTyped)
player:EmitSound("npc/overwatch/radiovoice/off4.wav");
end;
end;

player.typingBeep = nil;
end;

-- Called when a player stuns an entity.
function Schema:PlayerStunEntity(player, entity)
local target = Clockwork.entity:GetPlayer(entity);
local strength = Clockwork.attributes:Fraction(player, ATB_STRENGTH, 12, 6);

player:ProgressAttribute(ATB_STRENGTH, 0.5, true);

if (target and target:Alive()) then
local curTime = CurTime();

if (target.nextStunInfo and curTime <= target.nextStunInfo[2]) then
target.nextStunInfo[1] = target.nextStunInfo[1] + 1;
target.nextStunInfo[2] = curTime + 2;

if (target.nextStunInfo[1] == 3) then
Clockwork.player:SetRagdollState( target, RAGDOLL_KNOCKEDOUT, Clockwork.config:Get("knockout_time"):Get() );
end;
else
target.nextStunInfo = {0, curTime + 2};
end;

target:ViewPunch( Angle(12 + strength, 0, 0) );

Clockwork.datastream:Start(target, "Stunned", 0.5);
end;
end;
@@ -334,11 +308,11 @@ end;
-- Called when a player's inventory item has been updated.
function Schema:PlayerInventoryItemUpdated(player, itemTable, amount, force)
local clothes = player:GetCharacterData("clothes");

if (clothes == itemTable.index) then
if (!player:HasItemByID(itemTable.uniqueID)) then
itemTable:OnChangeClothes(player, false);

player:SetCharacterData("clothes", nil);
end;
end;
@@ -354,7 +328,7 @@ end;
-- Called when a player's storage should close.
function Schema:PlayerStorageShouldClose(player, storage)
local entity = player:GetStorageEntity();

if (player.searching and entity:IsPlayer() and entity:GetSharedVar("tied") == 0) then
return true;
end;
@@ -370,10 +344,10 @@ end;
-- Called when a player presses F3.
function Schema:ShowSpare1(player)
local itemTable = player:FindItemByID("zip_tie");

if (!itemTable) then
Clockwork.player:Notify(player, "You do not own a zip tie!");

return;
end;

@@ -390,10 +364,10 @@ function Schema:PlayerFootstep(player, position, foot, sound, volume, recipientF
local running = nil;
local clothes = player:GetCharacterData("clothes");
local model = string.lower( player:GetModel() );

if (clothes) then
local itemTable = Clockwork.item:FindByID(clothes);

if (itemTable) then
if (player:IsRunning() or player:IsJogging()) then
if (itemTable.runSound) then
@@ -412,64 +386,64 @@ function Schema:PlayerFootstep(player, position, foot, sound, volume, recipientF
end;
end;
end;

if (player:IsRunning() or player:IsJogging()) then
running = true;
end;

if (running) then
if (string.find(model, "metrocop") or string.find(model, "shockcp") or string.find(model, "ghostcp") or string.find(model, "police")) then
if (foot == 0) then
local randomSounds = {1, 3, 5};
local randomNumber = math.random(1, 3);

sound = "npc/metropolice/gear"..randomSounds[randomNumber]..".wav";
else
local randomSounds = {2, 4, 6};
local randomNumber = math.random(1, 3);

sound = "npc/metropolice/gear"..randomSounds[randomNumber]..".wav";
end;
elseif (string.find(model, "combine")) then
if (foot == 0) then
local randomSounds = {1, 3, 5};
local randomNumber = math.random(1, 3);

sound = "npc/combine_soldier/gear"..randomSounds[randomNumber]..".wav";
else
local randomSounds = {2, 4, 6};
local randomNumber = math.random(1, 3);

sound = "npc/combine_soldier/gear"..randomSounds[randomNumber]..".wav";
end;
end;
end;

player:EmitSound(sound);

return true;
end;

-- Called when a player attempts to spawn a prop.
function Schema:PlayerSpawnProp(player, model)
if (!player:IsAdmin() and Clockwork.config:Get("cwu_props"):Get()) then
if (player:GetFaction() == FACTION_CITIZEN) then

if (player:GetCharacterData("customclass") != "Civil Worker's Union") then
model = string.Replace(model, "\\", "/");
model = string.Replace(model, "//", "/");
model = string.lower(model);

if (string.find(model, "bed")) then
Clockwork.player:Notify(player, "You are not in the Civil Worker's Union!");

return false;
end;

for k, v in pairs(self.cwuProps) do
if (string.lower(v) == model) then
Clockwork.player:Notify(player, "You are not in the Civil Worker's Union!");

return false;
end;
end;
@@ -482,7 +456,7 @@ end;
function Schema:PlayerSpawnObject(player)
if (player:GetSharedVar("tied") != 0 or self.scanners[player]) then
Clockwork.player:Notify(player, "You don't have permission to do this right now!");

return false;
end;
end;
@@ -501,7 +475,7 @@ function Schema:PlayerCanBreachEntity(player, entity)
if (string.lower( entity:GetClass() ) == "func_door_rotating") then
return false;
end;

if (Clockwork.entity:IsDoor(entity)) then
if (!Clockwork.entity:IsDoorFalse(entity)) then
return true;
@@ -528,22 +502,22 @@ function Schema:PlayerCanRadio(player, text, listeners, eavesdroppers)
if (player:HasItemByID("handheld_radio") or self.scanners[player]) then
if (!player:GetCharacterData("frequency")) then
Clockwork.player:Notify(player, "You need to set the radio frequency first!");

return false;
end;
else
Clockwork.player:Notify(player, "You do not own a radio!");

return false;
end;
end;

-- Called when a player's character has initialized.
function Schema:PlayerCharacterInitialized(player)
local faction = player:GetFaction();

if (self:PlayerIsCombine(player)) then

for k, v in pairs(Clockwork.class.stored) do
if (v.factions and table.HasValue(v.factions, faction)) then
if (#_team.GetPlayers(v.index) < Clockwork.class:GetLimit(v.name)) then
@@ -568,7 +542,7 @@ end;
function Schema:PlayerNameChanged(player, previousName, newName)
if (self:PlayerIsCombine(player)) then
local faction = player:GetFaction();

if (faction == FACTION_OTA) then
if (!self:IsStringCombineRank(previousName, "OWS") and self:IsStringCombineRank(newName, "OWS")) then
Clockwork.class:Set(player, CLASS_OWS);
@@ -578,7 +552,7 @@ function Schema:PlayerNameChanged(player, previousName, newName)
elseif (faction == FACTION_MPF) then
if (!self:IsStringCombineRank(previousName, "SCN") and self:IsStringCombineRank(newName, "SCN")) then
Clockwork.class:Set(player, CLASS_MPS, true);

self:MakePlayerScanner(player, true);
elseif (!self:IsStringCombineRank(previousName, "RCT") and self:IsStringCombineRank(newName, "RCT")) then
Clockwork.class:Set(player, CLASS_MPR);
@@ -595,7 +569,7 @@ function Schema:PlayerNameChanged(player, previousName, newName)
Clockwork.class:Set(player, CLASS_MPU);
end;
end;

if (!self:IsStringCombineRank(previousName, "GHOST") and self:IsStringCombineRank(newName, "GHOST")) then
player:SetModel("models/eliteghostcp.mdl");
end;
@@ -617,24 +591,24 @@ function Schema:KeyPress(player, key)
local untieTime = Schema:GetDexterityTime(player);
local target = player:GetEyeTraceNoCursor().Entity;
local entity = target;

if (IsValid(target)) then
target = Clockwork.entity:GetPlayer(target);

if (target and player:GetSharedVar("tied") == 0) then
if (target:GetShootPos():Distance( player:GetShootPos() ) <= 192) then
if (target:GetSharedVar("tied") != 0) then
Clockwork.player:SetAction(player, "untie", untieTime);

Clockwork.player:EntityConditionTimer(player, target, entity, untieTime, 192, function()
return player:Alive() and !player:IsRagdolled() and player:GetSharedVar("tied") == 0;
end, function(success)
if (success) then
self:TiePlayer(target, false);

player:ProgressAttribute(ATB_DEXTERITY, 15, true);
end;

Clockwork.player:SetAction(player, "untie", false);
end);
end;
@@ -645,10 +619,10 @@ function Schema:KeyPress(player, key)
elseif (key == IN_ATTACK or key == IN_ATTACK2) then
if (self.scanners[player]) then
local scanner = self.scanners[player][1];

if (IsValid(scanner)) then
player.nextScannerSound = CurTime() + math.random(8, 48);

scanner:EmitSound( self.scannerSounds[ math.random(1, #self.scannerSounds) ] );
end;
end;
@@ -657,17 +631,17 @@ function Schema:KeyPress(player, key)
local scanner = self.scanners[player][1];
local curTime = CurTime();
local marker = self.scanners[player][2];

if (IsValid(scanner)) then
local position = scanner:GetPos();

for k, v in ipairs( ents.FindInSphere(position, 384) ) do
if (v:IsPlayer() and v:HasInitialized() and !self:PlayerIsCombine(v)) then
local playerPosition = v:GetPos();
local scannerDot = scanner:GetAimVector():Dot( (playerPosition - position):GetNormal() );
local playerDot = v:GetAimVector():Dot( (position - playerPosition):GetNormal() );
local threshold = 0.2 + math.Clamp( (0.6 / 384) * playerPosition:Distance(position), 0, 0.6 );

if (Clockwork.player:CanSeeEntity( v, scanner, 0.9, {marker} ) and playerDot >= threshold and scannerDot >= threshold) then
if (player != v) then
if (v:GetFaction() == FACTION_CITIZEN) then
@@ -679,13 +653,13 @@ function Schema:KeyPress(player, key)
end);
end;
end;

Clockwork.datastream:Start(v, "Stunned", 3);
end;
end;
end;
end;

scanner:EmitSound("npc/scanner/scanner_photo1.wav");
end;
end;
@@ -701,27 +675,27 @@ function Schema:Tick()
for k, v in pairs(self.scanners) do
local scanner = v[1];
local marker = v[2];

if (IsValid(k)) then
if (IsValid(scanner) and IsValid(marker)) then
if (k:KeyDown(IN_FORWARD)) then
local position = scanner:GetPos() + (scanner:GetForward() * 25) + (scanner:GetUp() * -64);

if (k:KeyDown(IN_SPEED)) then
marker:SetPos( position + (k:GetAimVector() * 64) );
else
marker:SetPos( position + (k:GetAimVector() * 128) );
end;

scanner.followTarget = nil;
end;

if (IsValid(scanner.followTarget)) then
scanner:Input("SetFollowTarget", scanner.followTarget, scanner.followTarget, "!activator");
else
scanner:Fire("SetFollowTarget", "marker_"..k:UniqueID(), 0);
end;

if (scannerClass == "npc_cscanner" and self:IsPlayerCombineRank(k, "SYNTH")) then
self:MakePlayerScanner(k, true);
elseif (scannerClass == "npc_clawscanner" and !self:IsPlayerCombineRank(k, "SYNTH")) then
@@ -734,11 +708,11 @@ function Schema:Tick()
if (IsValid(scanner)) then
scanner:Remove();
end;

if (IsValid(marker)) then
marker:Remove();
end;

self.scanners[k] = nil;
end;
end;
@@ -772,7 +746,7 @@ function Schema:PlayerCanSwitchCharacter(player, character)
if (player:GetCharacterData("permakilled")) then
return true;
end;

if (player:GetSharedVar("tied") != 0) then
return false, "You cannot switch to this character while tied!";
end;
@@ -790,7 +764,7 @@ function Schema:PlayerAdjustCharacterScreenInfo(player, character, info)
if (character.data["permakilled"]) then
info.details = "This character is permanently killed.";
end;

if (info.faction == FACTION_OTA) then
if (self:IsStringCombineRank(info.name, "EOW")) then
info.model = "models/combine_super_soldier.mdl";
@@ -811,12 +785,12 @@ function Schema:PlayerAdjustCharacterScreenInfo(player, character, info)
elseif (self:IsStringCombineRank(info.name, "OfC")) then
info.model = "models/policetrench.mdl";
end;

if (self:IsStringCombineRank(info.name, "GHOST")) then
info.model = "models/eliteghostcp.mdl";
end;
end;

if (character.data["customclass"]) then
info.customClass = character.data["customclass"];
end;
@@ -831,23 +805,23 @@ function Schema:ChatBoxMessageAdded(info)
local players = _player.GetAll();
local radios = ents.FindByClass("cw_radio");
local data = {};

for k, v in ipairs(radios) do
if (!v:IsOff() and info.speaker:GetPos():Distance( v:GetPos() ) <= 80) then
local frequency = v:GetFrequency();

if (frequency != 0) then
info.shouldSend = false;
info.listeners = {};
data.frequency = frequency;
data.position = v:GetPos();
data.entity = v;

break;
end;
end;
end;

if (IsValid(data.entity) and data.frequency != "") then
for k, v in ipairs(players) do
if (v:HasInitialized() and v:Alive() and !v:IsRagdolled(RAGDOLL_FALLENOVER)) then
@@ -859,42 +833,42 @@ function Schema:ChatBoxMessageAdded(info)
end;
end;
end;

for k, v in ipairs(radios) do
local radioPosition = v:GetPos();
local radioFrequency = v:GetFrequency();

if (!v:IsOff() and radioFrequency == data.frequency) then
for k2, v2 in ipairs(players) do
if (v2:HasInitialized() and !listeners[v2] and !eavesdroppers[v2]) then
if (v2:GetPos():Distance(radioPosition) <= (talkRadius * 2)) then
eavesdroppers[v2] = v2;
end;
end;

break;
end;
end;
end;

if (table.Count(listeners) > 0) then
Clockwork.chatBox:Add(listeners, info.speaker, "radio", info.text);
end;

if (table.Count(eavesdroppers) > 0) then
Clockwork.chatBox:Add(eavesdroppers, info.speaker, "radio_eavesdrop", info.text);
end;

table.Merge(info.listeners, listeners);
table.Merge(info.listeners, eavesdroppers);
end;
end;

if (info.voice) then
if (IsValid(info.speaker) and info.speaker:HasInitialized()) then
info.speaker:EmitSound(info.voice.sound, info.voice.volume);
end;

if (info.voice.global) then
for k, v in pairs(info.listeners) do
if (v != info.speaker) then
@@ -910,24 +884,24 @@ function Schema:PlayerRadioUsed(player, text, listeners, eavesdroppers)
local newEavesdroppers = {};
local talkRadius = Clockwork.config:Get("talk_radius"):Get() * 2;
local frequency = player:GetCharacterData("frequency");

for k, v in ipairs( ents.FindByClass("cw_radio") ) do
local radioPosition = v:GetPos();
local radioFrequency = v:GetFrequency();

if (!v:IsOff() and radioFrequency == frequency) then
for k2, v2 in ipairs( _player.GetAll() ) do
if (v2:HasInitialized() and !listeners[v2] and !eavesdroppers[v2]) then
if (v2:GetPos():Distance(radioPosition) <= talkRadius) then
newEavesdroppers[v2] = v2;
end;
end;

break;
end;
end;
end;

if (table.Count(newEavesdroppers) > 0) then
Clockwork.chatBox:Add(newEavesdroppers, player, "radio_eavesdrop", text);
end;
@@ -951,7 +925,7 @@ function Schema:CanTool(player, trace, tool)
if (!Clockwork.player:HasFlags(player, "w")) then
if (string.sub(tool, 1, 5) == "wire_" or string.sub(tool, 1, 6) == "wire2_") then
player:RunCommand("gmod_toolmode \"\"");

return false;
end;
end;
@@ -977,10 +951,10 @@ function Schema:PlayerSetSharedVars(player, curTime)
player:SetSharedVar( "citizenID", player:GetCharacterData("citizenid", "") );
player:SetSharedVar( "clothes", player:GetCharacterData("clothes", 0) );
player:SetSharedVar( "icon", player:GetCharacterData("icon", "") );

if (player:Alive() and !player:IsRagdolled() and player:GetVelocity():Length() > 0) then
local inventoryWeight = player:GetInventoryWeight();

if (inventoryWeight >= player:GetMaxWeight() / 4) then
player:ProgressAttribute(ATB_STRENGTH, inventoryWeight / 400, true);
end;
@@ -1002,33 +976,33 @@ function Schema:PlayerThink(player, curTime, infoTable)
end;
end;
end;

if (Clockwork.player:HasAnyFlags(player, "vV")) then
if (infoTable.wages == 0) then
infoTable.wages = 20;
end;
end;

if (self.scanners[player]) then
self:CalculateScannerThink(player, curTime);
end;

local acrobatics = Clockwork.attributes:Fraction(player, ATB_ACROBATICS, 100, 50);
local strength = Clockwork.attributes:Fraction(player, ATB_STRENGTH, 8, 4);
local agility = Clockwork.attributes:Fraction(player, ATB_AGILITY, 50, 25);

if (self:PlayerIsCombine(player)) then
infoTable.inventoryWeight = infoTable.inventoryWeight + 8;
end;

if (clothes != "") then
local itemTable = Clockwork.item:FindByID(clothes);

if (itemTable and itemTable.pocketSpace) then
infoTable.inventoryWeight = infoTable.inventoryWeight + itemTable.pocketSpace;
end;
end;

infoTable.inventoryWeight = infoTable.inventoryWeight + strength;
infoTable.jumpPower = infoTable.jumpPower + acrobatics;
infoTable.runSpeed = infoTable.runSpeed + agility;
@@ -1040,12 +1014,12 @@ function Schema:EntityRemoved(entity)
if (entity.areBelongings and entity.cwInventory and entity.cash) then
if (table.Count(entity.inventory) > 0 or entity.cash > 0) then
local belongings = ents.Create("cw_belongings");

belongings:SetAngles( Angle(0, 0, -90) );
belongings:SetData(entity.cwInventory, entity.cash);
belongings:SetPos( entity:GetPos() + Vector(0, 0, 32) );
belongings:Spawn();

entity.cwInventory = nil;
entity.cash = nil;
end;
@@ -1079,9 +1053,9 @@ function Schema:PlayerRestoreData(player, data)
if (!data["serverwhitelist"]) then
data["serverwhitelist"] = {};
end;

local serverWhitelistIdentity = Clockwork.config:Get("server_whitelist_identity"):Get();

if (serverWhitelistIdentity != "") then
if (!data["serverwhitelist"][serverWhitelistIdentity]) then
player:Kick("You aren't whitelisted");
@@ -1095,7 +1069,7 @@ function Schema:PlayerDoesHaveFlag(player, flag)
if (flag == "x" or flag == "1") then
return false;
end;

for k, v in pairs(self.customPermits) do
if (v.flag == flag) then
return false;
@@ -1132,15 +1106,15 @@ function Schema:PlayerCanUseCharacter(player, character)
elseif (character.faction == FACTION_MPF) then
if (self:IsStringCombineRank(character.name, "SCN")) then
local amount = 0;

for k, v in ipairs( _player.GetAll() ) do
if (v:HasInitialized() and self:PlayerIsCombine(v)) then
if (self:IsPlayerCombineRank(v, "SCN")) then
amount = amount + 1;
end;
end;
end;

if (amount >= 3) then
return "There are too many scanners online!";
end;
@@ -1158,10 +1132,10 @@ function Schema:PlayerCanUseCommand(player, commandTable, arguments)
"Request",
"Radio"
};

if (table.HasValue(blacklisted, commandTable.name)) then
Clockwork.player:Notify(player, "You cannot use this command when you are tied!");

return false;
end;
end;
@@ -1201,37 +1175,37 @@ end;
function Schema:PlayerCanChangeClass(player, class)
if (player:GetSharedVar("tied") != 0) then
Clockwork.player:Notify(player, "You cannot change classes when you are tied!");

return false;
elseif (self:PlayerIsCombine(player)) then
if (class == CLASS_MPS and !self:IsPlayerCombineRank(player, "SCN")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
elseif (class == CLASS_MPR and !self:IsPlayerCombineRank(player, "RCT")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
elseif (class == CLASS_EMP and !self:IsPlayerCombineRank(player, "EpU")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
elseif (class == CLASS_OWS and !self:IsPlayerCombineRank(player, "OWS")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
elseif (class == CLASS_EOW and !self:IsPlayerCombineRank(player, "EOW")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
elseif (class == CLASS_MPU) then
if (self:IsPlayerCombineRank(player, "EpU")) then
Clockwork.player:Notify(player, "You are ranked too high for this class!");

return false;
elseif (self:IsPlayerCombineRank(player, "RCT")) then
Clockwork.player:Notify(player, "You are not ranked high enough for this class!");

return false;
end;
end;
@@ -1243,7 +1217,7 @@ function Schema:PlayerUse(player, entity)
local overlayText = entity:GetNetworkedString("GModOverlayText");
local curTime = CurTime();
local faction = player:GetFaction();

if (string.find(overlayText, "CA")) then
if (faction != FACTION_ADMIN) then
return false;
@@ -1263,40 +1237,40 @@ function Schema:PlayerUse(player, entity)
end;
end;
end;

if (self.scanners[player]) then
return false;
end;

if (entity.bustedDown) then
return false;
end;

if (player:KeyDown(IN_SPEED) and Clockwork.entity:IsDoor(entity)) then
if ((self:PlayerIsCombine(player) or player:GetFaction() == FACTION_ADMIN) and IsValid(entity.combineLock)) then
if (!player.nextCombineLock or curTime >= player.nextCombineLock) then
entity.combineLock:ToggleWithChecks(player);

player.nextCombineLock = curTime + 3;
end;

return false;
end;
end;

if (player:GetSharedVar("tied") != 0) then
if (entity:IsVehicle()) then
if (Clockwork.entity:IsChairEntity(entity) or Clockwork.entity:IsPodEntity(entity)) then
return;
end;
end;

if (!player.nextTieNotify or player.nextTieNotify < CurTime()) then
Clockwork.player:Notify(player, "You cannot use that when you are tied!");

player.nextTieNotify = CurTime() + 2;
end;

return false;
end;
end;
@@ -1307,13 +1281,13 @@ function Schema:PlayerCanDestroyItem(player, itemTable, noMessage)
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot destroy items when you are a scanner!");
end;

return false;
elseif (player:GetSharedVar("tied") != 0) then
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot destroy items when you are tied!");
end;

return false;
end;
end;
@@ -1324,13 +1298,13 @@ function Schema:PlayerCanDropItem(player, itemTable, noMessage)
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot drop items when you are a scanner!");
end;

return false;
elseif (player:GetSharedVar("tied") != 0) then
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot drop items when you are tied!");
end;

return false;
end;
end;
@@ -1341,25 +1315,25 @@ function Schema:PlayerCanUseItem(player, itemTable, noMessage)
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot use items when you are a scanner!");
end;

return false;
elseif (player:GetSharedVar("tied") != 0) then
if (!noMessage) then
Clockwork.player:Notify(player, "You cannot use items when you are tied!");
end;

return false;
end;

if (Clockwork.item:IsWeapon(itemTable) and !itemTable:IsFakeWeapon()) then
local secondaryWeapon;
local primaryWeapon;
local sideWeapon;
local fault;

for k, v in ipairs( player:GetWeapons() ) do
local weaponTable = Clockwork.item:GetByWeapon(v);

if (weaponTable and !weaponTable:IsFakeWeapon()) then
if (weaponTable("weight") >= 1) then
if (weaponTable("weight") <= 2) then
@@ -1372,7 +1346,7 @@ function Schema:PlayerCanUseItem(player, itemTable, noMessage)
end;
end;
end;

if (itemTable("weight") >= 1) then
if (itemTable("weight") <= 2) then
if (secondaryWeapon) then
@@ -1384,12 +1358,12 @@ function Schema:PlayerCanUseItem(player, itemTable, noMessage)
elseif (sideWeapon) then
fault = "You cannot use another melee weapon!";
end;

if (fault) then
if (!noMessage) then
Clockwork.player:Notify(player, fault);
end;

return false;
end;
end;
@@ -1406,15 +1380,15 @@ end;
function Schema:PlayerPlayDeathSound(player, gender)
if (self:PlayerIsCombine(player)) then
local sound = "npc/metropolice/die"..math.random(1, 4)..".wav";

for k, v in ipairs( _player.GetAll() ) do
if (v:HasInitialized()) then
if (self:PlayerIsCombine(v)) then
v:EmitSound(sound);
end;
end;
end;

return sound;
end;
end;
@@ -1435,11 +1409,11 @@ function Schema:ChatBoxAdjustInfo(info)
end;
end;
end;

if (info.class == "ic" or info.class == "yell" or info.class == "radio" or info.class == "whisper" or info.class == "request") then
if (IsValid(info.speaker) and info.speaker:HasInitialized()) then
local playerIsCombine = self:PlayerIsCombine(info.speaker);

if (playerIsCombine and self:IsPlayerCombineRank(info.speaker, "SCN")) then
for k, v in pairs(self.voices.stored.dispatchVoices) do
if (string.lower(info.text) == string.lower(v.command)) then
@@ -1448,18 +1422,18 @@ function Schema:ChatBoxAdjustInfo(info)
volume = 90,
sound = v.sound
};

if (info.class == "request" or info.class == "radio") then
voice.global = true;
elseif (info.class == "whisper") then
voice.volume = 80;
elseif (info.class == "yell") then
voice.volume = 100;
end;

info.text = "<:: "..v.phrase;
info.voice = voice;

return true;
end;
end;
@@ -1472,33 +1446,33 @@ function Schema:ChatBoxAdjustInfo(info)
volume = 80,
sound = v.sound
};

if (v.female and info.speaker:QueryCharacter("gender") == GENDER_FEMALE) then
voice.sound = string.Replace(voice.sound, "/male", "/female");
end;

if (info.class == "request" or info.class == "radio") then
voice.global = true;
elseif (info.class == "whisper") then
voice.volume = 60;
elseif (info.class == "yell") then
voice.volume = 100;
end;

if (playerIsCombine) then
info.text = "<:: "..v.phrase;
else
info.text = v.phrase;
end;

info.voice = voice;

return true;
end;
end;
end;
end;

if (playerIsCombine) then
if (string.sub(info.text, 1, 4) != "<:: ") then
info.text = "<:: "..info.text;
@@ -1509,9 +1483,9 @@ function Schema:ChatBoxAdjustInfo(info)
for k, v in pairs(self.voices.stored.dispatchVoices) do
if (string.lower(info.text) == string.lower(v.command)) then
Clockwork.player:PlaySound(nil, v.sound);

info.text = v.phrase;

return true;
end;
end;
@@ -1522,15 +1496,15 @@ end;
function Schema:PlayerDestroyGenerator(player, entity, generator)
if (self:PlayerIsCombine(player)) then
local players = {};

for k, v in ipairs( _player.GetAll() ) do
if (v:HasInitialized()) then
if (self:PlayerIsCombine(v)) then
players[#players + 1] = v;
end;
end;
end;

for k, v in pairs(players) do
Clockwork.player:GiveCash( v, generator.cash / 4, "destroying a "..string.lower(generator.name) );
end;
@@ -1542,41 +1516,41 @@ end;
-- Called just before a player dies.
function Schema:DoPlayerDeath(player, attacker, damageInfo)
local clothes = player:GetCharacterData("clothes");

if (clothes) then
player:GiveItem(Clockwork.item:CreateInstance(clothes));
player:SetCharacterData("clothes", nil);
end;

player.beingSearched = nil;
player.searching = nil;

self:TiePlayer(player, false, true);
end;

-- Called when a player dies.
function Schema:PlayerDeath(player, inflictor, attacker, damageInfo)
if (self:PlayerIsCombine(player)) then
local location = self:PlayerGetLocation(player);

self:AddCombineDisplayLine("Downloading lost biosignal...", Color(255, 255, 255, 255), nil, player);
self:AddCombineDisplayLine("WARNING! Biosignal lost for protection team unit at "..location.."...", Color(255, 0, 0, 255), nil, player);

if (self.scanners[player]) then
if (IsValid( self.scanners[player][1] )) then
if (damageInfo != true) then
self.scanners[player][1]:TakeDamage(self.scanners[player][1]:Health() + 100);
end;
end;
end;

for k, v in ipairs( _player.GetAll() ) do
if (self:PlayerIsCombine(v)) then
v:EmitSound("npc/overwatch/radiovoice/on1.wav");
v:EmitSound("npc/overwatch/radiovoice/lostbiosignalforunit.wav");
end;
end;

timer.Simple(1.5, function()
for k, v in ipairs( _player.GetAll() ) do
if (self:PlayerIsCombine(v)) then
@@ -1585,12 +1559,12 @@ function Schema:PlayerDeath(player, inflictor, attacker, damageInfo)
end;
end);
end;

if (!player:GetCharacterData("permakilled")) then
if (( attacker:IsPlayer() or attacker:IsNPC() ) and damageInfo) then
local miscellaneousDamage = damageInfo:IsBulletDamage() or damageInfo:IsFallDamage() or damageInfo:IsExplosionDamage();
local meleeDamage = damageInfo:IsDamageType(DMG_CLUB) or damageInfo:IsDamageType(DMG_SLASH);

if (miscellaneousDamage or meleeDamage) then
if (Clockwork.kernel:GetSharedVar("PKMode") == 1) then
self:PermaKillPlayer(player, player:GetRagdollEntity());
@@ -1609,37 +1583,49 @@ end;
-- Called just after a player spawns.
function Schema:PostPlayerSpawn(player, lightSpawn, changeClass, firstSpawn)
local clothes = player:GetCharacterData("clothes");

if (!lightSpawn) then
player:SetSharedVar("antidepressants", 0);

Clockwork.datastream:Start(player, "ClearEffects", true);

player.beingSearched = nil;
player.searching = nil;

if (self:PlayerIsCombine(player) or player:GetFaction() == FACTION_ADMIN) then
if (player:GetFaction() == FACTION_MILITARY) then
if (player:GetFaction() == FACTION_OTA) then
player:SetMaxHealth(150);
player:SetMaxArmor(150);
player:SetHealth(150);
player:SetArmor(150);
elseif (!self:IsPlayerCombineRank(player, "RCT")) then
player:SetArmor(100);
else
player:SetArmor(50);
end;
end;


if (self:PlayerIsCombine(player) and player:GetAmmoCount("pistol") == 0) then
if (!player:HasItemByID("ammo_pistol")) then
player:GiveItem(Clockwork.item:CreateInstance("ammo_pistol"), true);
player:GiveItem(Clockwork.item:CreateInstance("ammo_pistol"), true);
end;
end;
end;

if (self:IsPlayerCombineRank(player, "SCN")) then
self:MakePlayerScanner(player, true, lightSpawn);
else
self:ResetPlayerScanner(player);
end;

if (player:GetSharedVar("tied") != 0) then
self:TiePlayer(player, true);
end;

if (clothes) then
local itemTable = Clockwork.item:FindByID(clothes);

if (itemTable and player:HasItemByID(itemTable.uniqueID)) then
self:PlayerWearClothes(player, itemTable);
else
@@ -1651,10 +1637,10 @@ end;
-- Called when a player spawns lightly.
function Schema:PostPlayerLightSpawn(player, weapons, ammo, special)
local clothes = player:GetCharacterData("clothes");

if (clothes) then
local itemTable = Clockwork.item:FindByID(clothes);

if (itemTable) then
itemTable:OnChangeClothes(player, true);
end;
@@ -1699,7 +1685,7 @@ end;
-- Called when a player takes damage.
function Schema:PlayerTakeDamage(player, inflictor, attacker, hitGroup, damageInfo)
local curTime = CurTime();

if (player:Armor() <= 0) then
Clockwork.datastream:Start(player, "Stunned", 0.5);
else
@@ -1730,7 +1716,7 @@ end;
-- Called when a player's limb takes damage.
function Schema:PlayerLimbTakeDamage(player, hitGroup, damage)
local limbDamage = Clockwork.limb:GetDamage(player, hitGroup);

if (hitGroup == HITGROUP_HEAD) then
player:BoostAttribute("Limb Damage", ATB_MEDICAL, -limbDamage);
elseif (hitGroup == HITGROUP_CHEST or hitGroup == HITGROUP_STOMACH) then
@@ -1748,13 +1734,13 @@ end;
function Schema:PlayerScaleDamageByHitGroup(player, attacker, hitGroup, damageInfo, baseDamage)
local endurance = Clockwork.attributes:Fraction(player, ATB_ENDURANCE, 0.75, 0.75);
local clothes = player:GetCharacterData("clothes");

damageInfo:ScaleDamage(1.5 - endurance);

if (damageInfo:IsBulletDamage()) then
if (clothes and damageInfo:IsBulletDamage()) then
local itemTable = Clockwork.item:FindByID(clothes);

if (itemTable and itemTable.protection) then
damageInfo:ScaleDamage(1 - itemTable.protection);
end;
@@ -1770,52 +1756,52 @@ function Schema:EntityTakeDamage(entity, damageInfo)
local damage = damageInfo:GetDamage();
local curTime = CurTime();
local doDoorDamage = nil;

if (player) then
if (!player.nextEnduranceTime or CurTime() > player.nextEnduranceTime) then
player:ProgressAttribute(ATB_ENDURANCE, math.Clamp(damageInfo:GetDamage(), 0, 75) / 10, true);
player.nextEnduranceTime = CurTime() + 2;
end;

if (self.scanners[player]) then
entity:EmitSound("npc/scanner/scanner_pain"..math.random(1, 2)..".wav");

if (entity:Health() > 50 and entity:Health() - damageInfo:GetDamage() <= 50) then
entity:EmitSound("npc/scanner/scanner_siren1.wav");
elseif (entity:Health() > 25 and entity:Health() - damageInfo:GetDamage() <= 25) then
entity:EmitSound("npc/scanner/scanner_siren2.wav");
end;
end;

if (attacker:IsPlayer() and self:PlayerIsCombine(player)) then
if (attacker != player) then
local location = Schema:PlayerGetLocation(player);

if (!player.nextUnderFire or curTime >= player.nextUnderFire) then
player.nextUnderFire = curTime + 15;

Schema:AddCombineDisplayLine("Downloading trauma packet...", Color(255, 255, 255, 255), nil, player);
Schema:AddCombineDisplayLine("WARNING! Protection team unit enduring physical bodily trauma at "..location.."...", Color(255, 0, 0, 255), nil, player);
end;
end;
end;
end;

if (attacker:IsPlayer()) then
local strength = Clockwork.attributes:Fraction(attacker, ATB_STRENGTH, 1, 0.5);
local weapon = Clockwork.player:GetWeaponClass(attacker);

if (damageInfo:IsDamageType(DMG_CLUB) or damageInfo:IsDamageType(DMG_SLASH)) then
damageInfo:ScaleDamage(1 + strength);
end;

if (weapon == "weapon_357") then
damageInfo:ScaleDamage(0.25);
elseif (weapon == "weapon_crossbow") then
damageInfo:ScaleDamage(2);
elseif (weapon == "weapon_shotgun") then
damageInfo:ScaleDamage(3);

doDoorDamage = true;
elseif (weapon == "weapon_crowbar") then
damageInfo:ScaleDamage(0.25);
@@ -1826,27 +1812,27 @@ function Schema:EntityTakeDamage(entity, damageInfo)
end;
end;
end;

if (damageInfo:IsBulletDamage() and weapon != "weapon_shotgun") then
if (!IsValid(entity.combineLock) and !IsValid(entity.breach)) then
if (string.lower( entity:GetClass() ) == "prop_door_rotating") then
if (!Clockwork.entity:IsDoorFalse(entity)) then
local damagePosition = damageInfo:GetDamagePosition();

if (entity:WorldToLocal(damagePosition):Distance( Vector(-1.0313, 41.8047, -8.1611) ) <= 8) then
entity.doorHealth = math.min( (entity.doorHealth or 50) - damageInfo:GetDamage(), 0 );

local effectData = EffectData();

effectData:SetStart(damagePosition);
effectData:SetOrigin(damagePosition);
effectData:SetScale(8);

util.Effect("GlassImpact", effectData, true, true);

if (entity.doorHealth <= 0) then
Clockwork.entity:OpenDoor( entity, 0, true, true, attacker:GetPos() );

entity.doorHealth = 50;
else
Clockwork.kernel:CreateTimer("reset_door_health_"..entity:EntIndex(), 60, 1, function()
@@ -1860,33 +1846,33 @@ function Schema:EntityTakeDamage(entity, damageInfo)
end;
end;
end;

if (damageInfo:IsExplosionDamage()) then
damageInfo:ScaleDamage(2);
end;
elseif (attacker:IsNPC()) then
damageInfo:ScaleDamage(0.5);
end;

if (damageInfo:IsExplosionDamage() or doDoorDamage) then
if (!IsValid(entity.combineLock) and !IsValid(entity.breach)) then
if (string.lower( entity:GetClass() ) == "prop_door_rotating") then
if (!Clockwork.entity:IsDoorFalse(entity)) then
if (attacker:GetPos():Distance( entity:GetPos() ) <= 96) then
entity.doorHealth = math.min( (entity.doorHealth or 50) - damageInfo:GetDamage(), 0 );

local damagePosition = damageInfo:GetDamagePosition();
local effectData = EffectData();

effectData:SetStart(damagePosition);
effectData:SetOrigin(damagePosition);
effectData:SetScale(8);

util.Effect("GlassImpact", effectData, true, true);

if (entity.doorHealth <= 0) then
self:BustDownDoor(attacker, entity);

entity.doorHealth = 50;
else
Clockwork.kernel:CreateTimer("reset_door_health_"..entity:EntIndex(), 60, 1, function()
@@ -1900,4 +1886,4 @@ function Schema:EntityTakeDamage(entity, damageInfo)
end;
end;
end;
end;
end;