SHARE
TWEET

Untitled

a guest Aug 18th, 2019 141 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. include("sh_gangs.lua")
  2. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3. -- Gang Wars & Gang Bases
  4. util.AddNetworkString("GangBaseDialog")
  5. util.AddNetworkString("GangWarStartDialog")
  6. util.AddNetworkString("GangWarOverDialog")
  7. util.AddNetworkString("ds_gang_points") -- set gang points on the client
  8. util.AddNetworkString("set_gang_news") -- set gang news msg from client
  9. util.AddNetworkString("sv_refresh_topgangs")
  10. GangWars.GangBases = {}
  11. GangWars.GangWars = {}
  12. local meta = FindMetaTable("Player")
  13.  
  14. function meta:GetGangBase()
  15.     return GangWars.GangBases[self:Gang()]
  16. end
  17.  
  18. local function GiveGangMembersXP(gang, xp)
  19.     for k, v in pairs(player.GetAll()) do
  20.         if v:Gang() == gang then
  21.             GangWars.AddXP(v, xp)
  22.         end
  23.     end
  24. end
  25.  
  26. GangWars.GiveGangMembersXP = GiveGangMembersXP
  27.  
  28. -- this function will give a % of required XP
  29. local function GiveGangMembersXPAuto(gang, perc)
  30.     for k, v in pairs(player.GetAll()) do
  31.         if v:Gang() == gang then
  32.             local lvl = GangWars.GetLevel(v) + v:Tier()
  33.             local xp2l = GangWars.GetXP2L(lvl)
  34.             local xp = math.floor((xp2l / 100) * (perc or 50))
  35.             GangWars.AddXP(v, xp, true)
  36.         end
  37.     end
  38. end
  39.  
  40. GangWars.GiveGangMembersXPAuto = GiveGangMembersXPAuto
  41.  
  42. local function ServerHasGangVariance()
  43.     local gangs = {}
  44.  
  45.     for k, v in pairs(player.GetAll()) do
  46.         if v:Gang() ~= "" then
  47.             gangs[v:Gang()] = 1
  48.         end
  49.     end
  50.  
  51.     return table.Count(gangs) > 1
  52. end
  53.  
  54. local MIN_TIME_BETWEEN_GANG_BASES = (3600 + 1800)
  55.  
  56. function GangWars.SetGangBase(ply, base_building)
  57.     local gang = ply:Gang()
  58.     local bb = GangWars.FindBuildingByID(base_building)
  59.  
  60.     -- is gang ok?
  61.     if gang == "" then
  62.         Notify(ply, NOTIFY_ERROR, 4, "You are not in a gang")
  63.  
  64.         return
  65.     end
  66.  
  67.     -- is points ok?
  68.     if not ply.GangInfo or not ply.GangInfo.points or ply.GangInfo.points < 1000 then
  69.         Notify(ply, NOTIFY_ERROR, 4, "You need at least 1,000 points to make a Gang Base")
  70.  
  71.         return
  72.     end
  73.  
  74.     -- is this building inside a territory owned by our gang?
  75.     local building_is_in_territory = false
  76.     local territory = nil
  77.  
  78.     for k, v in pairs(GangWars.GangTerritories) do
  79.         if v:ObjectIsInside(bb) and v.owner and v.owner == gang then
  80.             building_is_in_territory = true
  81.             territory = v
  82.             break
  83.         end
  84.     end
  85.  
  86.     if not building_is_in_territory then
  87.         Notify(ply, NOTIFY_ERROR, 4, "You can only make a gang base within territory you own")
  88.  
  89.         return
  90.     end
  91.  
  92.     -- can we base?
  93.     isql:QueryValue("SELECT TIME_TO_SEC(TIMEDIFF(NOW(), `last_base`)) FROM `gw_gangs` WHERE `name` = " .. isql:Escape(gang), function(timediff)
  94.         -- is base ok?
  95.         if not bb or not bb.bdata or not bb.capture_point then
  96.             GangNotify(ply, NOTIFY_ERROR, 4, "You can't make a gang base here - " .. base_building)
  97.             --MsgN("bb = " .. tostring(bb))
  98.  
  99.             return
  100.         end
  101.  
  102.         -- are we at war?
  103.         if GangWars.GangWars[gang] then
  104.             GangNotify(ply, NOTIFY_ERROR, 4, "You can't change base while at war!")
  105.  
  106.             return
  107.         end
  108.  
  109.         -- do we have access?
  110.         if ply:GetNW2Int("gang_rank") > 2 then
  111.             GangNotify(ply, NOTIFY_ERROR, 4, "Gang Base can only be set by leader & vice leader")
  112.  
  113.             return
  114.         end
  115.  
  116.         -- is there already a base set? compare access levels
  117.         if GangWars.GangBases[gang] and IsValid(GangWars.GangBases[gang].owner) and GangWars.GangBases[gang].owner:GetNW2Int("gang_rank") < ply:GetNW2Int("gang_rank") then
  118.             GangNotify(ply, NOTIFY_ERROR, 4, "Your gang already has a base set")
  119.  
  120.             return
  121.         end
  122.  
  123.         -- Cancel / Un-set base
  124.         if GangWars.GangBases[gang] and GangWars.GangBases[gang].base == base_building then
  125.             NotifyGang(ply, NOTIFY_ERROR, 4, "Your Gang Base has been un-set. You have no base!")
  126.  
  127.             -- update building doors
  128.             for k, v in pairs(bb.doors) do
  129.                 v:SetNW2String("gang", "")
  130.             end
  131.  
  132.             -- set data
  133.             GangWars.GangBases[gang] = nil
  134.  
  135.             return
  136.         end
  137.  
  138.         -- timediff is the number of seconds since we last based. it must be at least 60 mins.
  139.         -- is time ok?
  140.         if not timediff or timediff < MIN_TIME_BETWEEN_GANG_BASES then
  141.             GangNotify(ply, NOTIFY_ERROR, 4, "You can't make a gang base for " .. math.floor((MIN_TIME_BETWEEN_GANG_BASES - (timediff or 60)) / 60) .. " minutes")
  142.  
  143.             return
  144.         end
  145.  
  146.         local newbase = GangWars.GangBases[gang] == nil and false or true
  147.         -- set database entry for last base
  148.         isql:Query("UPDATE `gw_gangs` SET `last_base` = NOW() WHERE `name` = " .. isql:Escape(gang))
  149.  
  150.         -- set base entry
  151.         GangWars.GangBases[gang] = {
  152.             owner = ply,
  153.             gang = gang,
  154.             base = base_building,
  155.             territory = territory
  156.         }
  157.  
  158.         -- set a gangbase flag here. this is used in UnOwn() in entity.lua to automaticly unset the GangBase entry, capture points use it too.
  159.         local building = bb
  160.         building.GangBase = gang
  161.  
  162.         --[[
  163.         // create the points tick timer
  164.         timer.Create("GangBase" .. gang, 60, 0, function()
  165.             if GangWars.GangBases[gang] then
  166.  
  167.                 // how many points should they earn? 50 base
  168.                 local points = 50
  169.  
  170.                 // launderers, printers, forges boost points by 5
  171.                 local contraband_owned_by_gang = 0;
  172.                 // count contraband which are plugged in, whos owner is in this gang and are a reasonable distance from base
  173.                 local counters = { "money_printer", "money_launderer", "material_forge" }
  174.                 for x, y in pairs(counters) do
  175.                     for k,v in pairs(ents.FindByClass(y) or {}) do
  176.                         if v:GetNW2Bool("connected") and v:GetNWEntity("owning_ent"):Gang() == gang and v:GetPos():DistToSqr( building:GetPos() ) < 1000000 then
  177.                             contraband_owned_by_gang = contraband_owned_by_gang + 1
  178.                         end
  179.                     end
  180.                 end
  181.  
  182.                 // boost points - +5 per contraband
  183.                 points = points + contraband_owned_by_gang * 5
  184.  
  185.                 if table.Count(player.GetAll()) < 10 or not ServerHasGangVariance() then
  186.                     NotifyGang(gang, NOTIFY_ERROR, 4, "No Gang Points with less than 10 people / no other Gangs on the server")
  187.                 else
  188.                     GangWars.DB.AddGangPoints( gang, points, function() end )
  189.                     NotifyGang(gang, NOTIFY_ERROR, 4, "Your base earned +" .. points .. " Gang Points")
  190.                 end
  191.             else
  192.                 timer.Remove("GangBase" .. gang)
  193.             end
  194.         end)
  195.         ]]
  196.         -- update clients? not needed because they only need to know this during war?
  197.         -- update building doors
  198.         for k, v in pairs(building.doors) do
  199.             v:SetNW2String("gang", gang)
  200.         end
  201.  
  202.         -- tell gang members
  203.         if newbase then
  204.             net.Start("GangBaseDialog")
  205.             net.Send(ply)
  206.             NotifyGang(gang, 4, 4, "Your Gang Base is set to " .. bb.bdata.name, true)
  207.         else
  208.             NotifyGang(gang, 4, 4, "Your Gang Base changed to " .. bb.bdata.name, true)
  209.         end
  210.     end)
  211. end
  212.  
  213. AddChatCommand("/base", function(ply)
  214.     local trace = ply:GetEyeTrace()
  215.  
  216.     if IsValid(trace.Entity) and trace.Entity:IsOwnable() and trace.Entity:IsDoor() and ply:GetPos():Distance(trace.Entity:GetPos()) < 200 then
  217.         if RPArrestedPlayers[ply:SteamID()] then
  218.             Notify(ply, 1, 5, "You can't do that while arrested!")
  219.  
  220.             return ""
  221.         end
  222.  
  223.         if trace.Entity:GetNW2Bool("nonOwnable") or trace.Entity:GetNW2Bool("BankerOwnable") then
  224.             Notify(ply, 1, 5, "This door can not be owned")
  225.  
  226.             return ""
  227.         end
  228.  
  229.         if not trace.Entity:OwnedBy(ply) then
  230.             Notify(ply, 1, 5, "You don't own this building")
  231.  
  232.             return ""
  233.         end
  234.  
  235.         GangWars.SetGangBase(ply, trace.Entity.building.bdata.id)
  236.     end
  237.  
  238.     return ""
  239. end)
  240.  
  241. -- This is fking lazy and should be rewritten using a proper net message
  242. function GangWars.ClientUpdateGangWarData(ply)
  243.     local war = GangWars.GangWars[ply:Gang()]
  244.  
  245.     if war then
  246.         if war.role == "attacking" then
  247.             local ebase = GangWars.GangBases[war.rival]
  248.             ply:SendLua("GangWars.GangWar = { role = '" .. war.role .. "', rival = '" .. war.rival .. "', base = '" .. ebase.base .. "', tokens = " .. war.tokens .. " }")
  249.         else
  250.             local base = GangWars.GangBases[war.gang]
  251.  
  252.             -- I've seen here there be no base entry! So we're getting an update on a war where the defense no longer has a base? def should lose?
  253.             if not base then
  254.                 GangWars.FinishGangWar(war.rival)
  255.  
  256.                 return
  257.             end
  258.  
  259.             ply:SendLua("GangWars.GangWar = { role = '" .. war.role .. "', rival = '" .. war.rival .. "', base = '" .. base.base .. "', tokens = " .. GangWars.GangWars[war.rival].tokens .. " }")
  260.         end
  261.     else
  262.         ply:SendLua("GangWars.GangWar = nil")
  263.     end
  264. end
  265.  
  266. --AddChatCommand("/testwar", function(ply, args)
  267. --  GangWars.StartGangWar( ply, ply:Gang() )
  268. --  return ""
  269. --end)
  270. AddChatCommand("/war", function(ply, args)
  271.     local trace = ply:GetEyeTrace()
  272.  
  273.     if IsValid(trace.Entity) and trace.Entity:IsPlayer() then
  274.         GangWars.StartGangWar(ply, trace.Entity:Gang())
  275.     elseif IsValid(trace.Entity) and trace.Entity.building and trace.Entity.building.bdata and trace.Entity.building.bdata.id and trace.Entity.building.GangBase then
  276.         -- search for a gang base at this ID
  277.         for k, v in pairs(GangWars.GangBases) do
  278.             if v.base == trace.Entity.building.bdata.id then
  279.                 GangWars.StartGangWar(ply, v.gang)
  280.  
  281.                 return ""
  282.             end
  283.         end
  284.     end
  285.  
  286.     return ""
  287. end)
  288.  
  289. function GangWars.StartGangWar(ply, rival)
  290.     local gang = ply:Gang()
  291.     -- TODO: check not fighting ourself
  292.     if gang == "" or rival == gang then return end --GangNotify(ply, NOTIFY_ERROR, 4, "") -- check not at war
  293.  
  294.     if GangWars.GangWars[rival] then
  295.         GangNotify(ply, NOTIFY_ERROR, 4, rival .. " are already at war")
  296.  
  297.         return
  298.     end
  299.  
  300.     -- check if we're already fighting?
  301.     if GangWars.GangWars[gang] then
  302.         GangNotify(ply, NOTIFY_ERROR, 4, "You are already fighting " .. GangWars.GangWars[gang].rival .. "")
  303.  
  304.         return
  305.     end
  306.  
  307.     -- do we have access?
  308.     --if ply:GetNW2Int("gang_rank") > 2 then
  309.     --  GangNotify(ply, NOTIFY_ERROR, 4, "Gang War can only be started by leader or vice leader")
  310.     --  return
  311.     --end
  312.     -- check we have bases
  313.     if not GangWars.GangBases[rival] then
  314.         GangNotify(ply, NOTIFY_ERROR, 4, rival .. " do not have a gang base")
  315.  
  316.         return
  317.     end
  318.  
  319.     -- check their base is not on protection
  320.     if GangWars.GangBases[rival].protected and GangWars.GangBases[rival].protected > CurTime() then
  321.         local ptime = math.max(1, math.floor((GangWars.GangBases[rival].protected - CurTime()) / 60))
  322.         GangNotify(ply, NOTIFY_ERROR, 4, rival .. " cannot be raided! Wait " .. ptime .. " minutes")
  323.  
  324.         return
  325.     end
  326.  
  327.     --if GangWars.GangBases[gang] then
  328.     --  GangNotify(ply, NOTIFY_ERROR, 4, "You don't have a Gang Base! Buy a building, press F2 on a door and click 'Set Gang Base'" )
  329.     --  return
  330.     --end
  331.     -- check war time limit
  332.     -- verify time is ok
  333.     isql:QueryValue("SELECT TIME_TO_SEC(TIMEDIFF(NOW(), time)) FROM `gw_time` WHERE name = " .. isql:Escape("gang_war_" .. ply:Gang()) .. ";", function(time)
  334.         local war_time = (60 * 60 * 6)
  335.  
  336.         if time and tonumber(time) < war_time then
  337.             GangNotify(ply, NOTIFY_ERROR, 4, "You can only start a war once every 3 hours! Wait " .. math.floor((war_time - tonumber(time)) / 60) .. " minutes")
  338.  
  339.             return
  340.         end
  341.  
  342.         isql:Query("UPDATE `gw_time` SET `time` = NOW() WHERE name = " .. isql:Escape("gang_war_" .. ply:Gang()) .. ";", function(d, s, err)
  343.             -- decide tokens by gang member count
  344.             local membercount = 0
  345.  
  346.             for k, v in pairs(player.GetAll()) do
  347.                 if v:Gang() == gang then
  348.                     membercount = membercount + 1
  349.                 end
  350.             end
  351.  
  352.             -- add war entires for both gangs
  353.             GangWars.GangWars[gang] = {
  354.                 gang = gang,
  355.                 rival = rival,
  356.                 role = "attacking",
  357.                 tokens = membercount * 3
  358.             }
  359.  
  360.             GangWars.GangWars[rival] = {
  361.                 gang = rival,
  362.                 rival = gang,
  363.                 role = "defending",
  364.                 tokens = membercount * 3
  365.             }
  366.  
  367.             -- update all clients in-game that war is active & starting now
  368.             for k, v in pairs(player.GetAll()) do
  369.                 if v:Gang() == gang then
  370.                     GangWars.ClientUpdateGangWarData(v)
  371.                     TimerNotify(v, 60 * 30, "Attack " .. rival)
  372.                     net.Start("GangWarStartDialog")
  373.                     net.WriteString("attacking")
  374.                     net.WriteString(rival)
  375.                     net.Send(v)
  376.                 end
  377.  
  378.                 if v:Gang() == rival then
  379.                     GangWars.ClientUpdateGangWarData(v)
  380.                     TimerNotify(v, 60 * 30, "Defend from " .. gang)
  381.                     net.Start("GangWarStartDialog")
  382.                     net.WriteString("defending")
  383.                     net.WriteString(gang)
  384.                     net.Send(v)
  385.                 end
  386.             end
  387.  
  388.             -- create timer to end the war in favour of the defenders
  389.             timer.Create("GangWar" .. gang, 60 * 30, 1, function()
  390.                 if GangWars.GangWars[rival] then
  391.                     GangWars.FinishGangWar(rival)
  392.                 end
  393.             end)
  394.  
  395.             -- use traditional notify for console message log
  396.             NotifyGang(gang, 4, 4, ply:Nick() .. " declared war on " .. rival, true)
  397.             NotifyGang(rival, 4, 4, ply:Nick() .. " of " .. gang .. " declared war on our gang!", true)
  398.             -- log
  399.             GangWars.GangLog(gang, rival, "War", ply, ply:Nick() .. " declared war on " .. rival)
  400.         end)
  401.     end)
  402. end
  403.  
  404. -- catch race conditions
  405. local FinishWarLimit = {}
  406.  
  407. function GangWars.FinishGangWar(win)
  408.     local winner = table.Copy(GangWars.GangWars[win])
  409.     local loser = table.Copy(GangWars.GangWars[winner.rival])
  410.  
  411.     if not winner or not loser then
  412.         MsgN("Error: couldn't find winner or loser in gang war? Winner was '" .. win .. "'")
  413.         GangWars.Log("error", "", "Couldn't find winner or loser in gang war? Winner was '" .. win .. "'")
  414.  
  415.         return
  416.     end
  417.  
  418.     local wl = winner.gang .. loser.gang
  419.     if FinishWarLimit[wl] and FinishWarLimit[wl] > CurTime() then return end
  420.     FinishWarLimit[wl] = CurTime() + 300
  421.  
  422.     -- determine points
  423.     GangWars.DB.GetGangPoints(loser.gang, function(points)
  424.         if not points then
  425.             MsgN("Error with Gang Points?")
  426.             GangWars.Log("error", "", "Finishing gang war couldn't find loser points for '" .. loser.gang .. "'")
  427.  
  428.             return
  429.         end
  430.  
  431.         local defenders = GangWars.GangWars[winner.gang].role == "defending" and GangWars.GangWars[winner.gang] or GangWars.GangWars[loser.gang]
  432.  
  433.         -- DEFENSE LOSES - LOSE 20% of points
  434.         if GangWars.GangWars[loser.gang].role == "defending" then
  435.             points = math.floor((points / 100) * 20)
  436.             local winpoints = math.floor(points / 2)
  437.             -- change points
  438.             GangWars.DB.AddGangPoints(winner.gang, winpoints, function() end)
  439.             GangWars.DB.AddGangPoints(loser.gang, -points, function() end)
  440.             -- member XP
  441.             GiveGangMembersXPAuto(winner.gang, 60)
  442.             -- notify
  443.             NotifyGang(winner.gang, 4, 4, "You won the war vs " .. loser.gang .. ", winning " .. winpoints .. " points", true)
  444.             NotifyGang(loser.gang, 4, 4, "You lost the war vs " .. winner.gang .. ", losing " .. points .. " points", true)
  445.  
  446.             -- defense should lose the base!
  447.             if GangWars.GangBases[defenders.gang] then
  448.                 -- find base
  449.                 local bb = GangWars.FindBuildingByID(GangWars.GangBases[defenders.gang].base)
  450.  
  451.                 -- update building doors
  452.                 for k, v in pairs(bb.doors) do
  453.                     v:SetNW2String("gang", "")
  454.                 end
  455.  
  456.                 -- set data
  457.                 GangWars.GangBases[defenders.gang] = nil
  458.             end
  459.             -- DEFENSE WINS - GAIN BONUS POINTS
  460.         else
  461.             points = 25000
  462.             -- member XP
  463.             GiveGangMembersXPAuto(winner.gang, 40)
  464.             -- change points
  465.             GangWars.DB.AddGangPoints(winner.gang, points, function() end)
  466.             -- notify
  467.             NotifyGang(winner.gang, 4, 4, "You defended against " .. loser.gang .. ", and gained +" .. points .. " bonus points", true)
  468.             NotifyGang(loser.gang, 4, 4, "You lost the war vs " .. winner.gang, true)
  469.  
  470.             -- set the base of the defense to protected status
  471.             if GangWars.GangBases[defenders.gang] then
  472.                 GangWars.GangBases[defenders.gang].protected = CurTime() + 60 * 40
  473.             end
  474.         end
  475.  
  476.         -- update wars won status
  477.         isql:Query("UPDATE `gw_gangs` SET `wars_won` = `wars_won` + 1 WHERE `name` = " .. isql:Escape(winner.gang))
  478.         isql:Query("UPDATE `gw_gangs` SET `wars_lost` = `wars_lost` + 1 WHERE `name` = " .. isql:Escape(loser.gang))
  479.  
  480.         -- update wars won status - defending gang lost
  481.         if GangWars.GangWars[loser.gang].role == "defending" then
  482.             isql:Query("UPDATE `gw_gangs` SET `att_won` = `att_won` + 1 WHERE `name` = " .. isql:Escape(winner.gang))
  483.             isql:Query("UPDATE `gw_gangs` SET `def_lost` = `def_lost` + 1 WHERE `name` = " .. isql:Escape(loser.gang))
  484.         else
  485.             isql:Query("UPDATE `gw_gangs` SET `def_won` = `def_won` + 1 WHERE `name` = " .. isql:Escape(winner.gang))
  486.             isql:Query("UPDATE `gw_gangs` SET `att_lost` = `att_lost` + 1 WHERE `name` = " .. isql:Escape(loser.gang))
  487.         end
  488.  
  489.         -- log
  490.         GangWars.Log("gangwar", "", winner.gang .. " won a war vs " .. loser.gang)
  491.         -- kill timers (only 1 will actually exist here)
  492.         timer.Remove("GangWar" .. winner.gang)
  493.         timer.Remove("GangWar" .. loser.gang)
  494.         FinishWarLimit[wl] = CurTime() + 300
  495.         -- clear data
  496.         GangWars.GangWars[winner.gang] = nil
  497.         GangWars.GangWars[loser.gang] = nil
  498.  
  499.         -- show dialogs
  500.         for k, v in pairs(player.GetAll()) do
  501.             if v:Gang() == winner.gang then
  502.                 net.Start("GangWarOverDialog")
  503.                 net.WriteString(loser.gang)
  504.                 net.WriteString("win")
  505.                 net.WriteInt(points, 32)
  506.                 net.Send(v)
  507.                 TimerNotifyClear(v)
  508.                 v:SendLua("GangWars.GangWar = nil")
  509.             elseif v:Gang() == loser.gang then
  510.                 net.Start("GangWarOverDialog")
  511.                 net.WriteString(winner.gang)
  512.                 net.WriteString("lose")
  513.                 net.WriteInt(0, 32)
  514.                 net.Send(v)
  515.                 TimerNotifyClear(v)
  516.                 --GangWars.ClientUpdateGangWarData( v )
  517.                 v:SendLua("GangWars.GangWar = nil")
  518.             end
  519.         end
  520.  
  521.         -- log in ganglog
  522.         GangWars.GangLog(winner.gang, "", "War Won", "none")
  523.         GangWars.GangLog(loser.gang, "", "War Lost", "none")
  524.     end)
  525. end
  526.  
  527. -- On player spawn, check their gang war info is set
  528. hook.Add("PlayerSpawn", function(ply)
  529.     GangWars.ClientUpdateGangWarData(ply)
  530. end)
  531.  
  532. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  533. -- Gang News
  534. net.Receive("set_gang_news", function(len, ply)
  535.     local gang = ply:Gang()
  536.     local news = net.ReadString()
  537.     -- sanitize the news
  538.     news = string.Replace(news, '<', '&lt;')
  539.     news = string.Replace(news, '>', '&gt;')
  540.     news = string.Replace(news, "\\n", '<br/>')
  541.  
  542.     GangWars.DB.GetPlayerGangRank(ply, function(rank)
  543.         if rank and rank == 1 then
  544.             -- Set news
  545.             isql:Query("UPDATE `gw_gangs` SET `message` = " .. isql:Escape(news) .. " WHERE `name` = " .. isql:Escape(gang), function()
  546.                 -- ensure we're updated
  547.                 Gang.SendInfo(ply, ply:Gang())
  548.             end)
  549.         else
  550.             GangNotify(ply, NOTIFY_ERROR, 4, "Only the leader can set the news")
  551.         end
  552.     end)
  553. end)
  554.  
  555. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  556. -- Gang Log
  557. function GangWars.GangLog(gang, log, event, member)
  558.     event = event or "none"
  559.  
  560.     if type(member) == "Player" and IsValid(member) then
  561.         member = member:SteamID()
  562.     end
  563.  
  564.     member = member or "none"
  565.     isql:Query("INSERT INTO `gw_gang_log` (`gang`, `date`, `log`, `event`, `member`) VALUES(" .. isql:Escape(gang) .. ", NOW(), " .. isql:Escape(log) .. ", " .. isql:Escape(event) .. ", " .. isql:Escape(member) .. ")")
  566. end
  567.  
  568. function GangWars.GangLogNumber(gang, number, event, member, log)
  569.     event = event or "none"
  570.  
  571.     if IsValid(member) and member:IsPlayer() then
  572.         member = member:SteamID()
  573.     end
  574.  
  575.     member = member or "none"
  576.  
  577.     if log then
  578.         isql:Query("INSERT INTO `gw_gang_log` (`gang`, `date`, `number`, `event`, `member`, `log`) VALUES(" .. isql:Escape(gang) .. ", NOW(), " .. isql:Escape(number) .. ", " .. isql:Escape(event) .. ", " .. isql:Escape(member) .. ", " .. isql:Escape(log) .. ")")
  579.     else
  580.         isql:Query("INSERT INTO `gw_gang_log` (`gang`, `date`, `number`, `event`, `member`) VALUES(" .. isql:Escape(gang) .. ", NOW(), " .. isql:Escape(number) .. ", " .. isql:Escape(event) .. ", " .. isql:Escape(member) .. ")")
  581.     end
  582. end
  583.  
  584. function meta:GangLogRefresh()
  585.     if not self.GangInfo or not self.GangInfo.name or self.GangInfo.name == "" then
  586.         self:SetDataset("gang_log", {})
  587.     else
  588.         self:SetDatasetQuery("gang_log", "SELECT DATE_FORMAT(`date`, '%D @ %H:%i:%s') AS `date`, `log` FROM `gw_gang_log` WHERE `gang` = " .. isql:Escape(self.GangInfo.name) .. " ORDER BY `date` DESC LIMIT 1000;")
  589.     end
  590. end
  591.  
  592. -- remove older entries than 24*7 hours from the gang log
  593. timer.Create("PruneGangLogs", 60 * 120, 0, function()
  594.     isql:Query("DELETE FROM `gw_gang_log` WHERE TIME_TO_SEC(TIMEDIFF(NOW(), `date`)) > 604800")
  595. end)
  596.  
  597. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  598. -- Gamemode Hooks
  599. local doonce = false
  600.  
  601. local function GangInitTerritories()
  602.     if doonce then return end
  603.     doonce = true
  604.     --[[
  605.     for _, t in ipairs( GangTerritory ) do
  606.         if t.map == string.lower(game.GetMap()) then
  607.             local ter = ents.Create("gang_territory")
  608.             ter:SetPos(t.pos)
  609.  
  610.             // Territory network ints
  611.             ter:SetNW2String("territory_owned", "")     // is it owned?
  612.             ter:SetNW2Int("territory_id", _)                // array index: GangTerritory[idx]
  613.             ter.captime = t.captime
  614.             ter.master = t.master
  615.             ter.territory = t
  616.             GangTerritory[_].ent = ter
  617.  
  618.             ter:Spawn()
  619.         end
  620.     end
  621.     ]]
  622.     -- Make the territory map in spawn
  623.     local tel = ents.Create("gw_territory_map")
  624.     tel:SetPos(GetNamedSpawn("spawn_map"))
  625.     tel:Spawn()
  626.  
  627.     if GetMapName() == "gw_downtown" then
  628.         tel:SetAngles(Angle(90, 90, 0))
  629.     else
  630.         tel:SetAngles(Angle(90, 90, 0))
  631.     end
  632.  
  633.     -- Make the top gangs display in spawn
  634.     local tel = ents.Create("gw_top_gangs")
  635.     tel:SetPos(GetNamedSpawn("spawn_topgangs"))
  636.     tel:Spawn()
  637.     tel:SetAngles(Angle(0, 0, 90))
  638.     -- HACK NPC's
  639.     --local tel = ents.Create("npc_gunsmith")
  640.     --tel:SetPos( GetNamedSpawn("gundealer") )
  641.     --tel:Spawn()
  642.     --local tel = ents.Create("npc_blacksmith")
  643.     --tel:SetPos( GetNamedSpawn("blacksmith") )
  644.     --tel:SetAngles(Angle(0,270,0))
  645.     --tel:Spawn()
  646.     --local tel = ents.Create("npc_armor")
  647.     --tel:SetPos( GetNamedSpawn("armorsmith") )
  648.     --tel:SetAngles(Angle(0,270,0))
  649.     --tel:Spawn()
  650.     local tel = ents.Create("npc_banker")
  651.     tel:SetPos(GetNamedSpawn("banker"))
  652.     tel:SetAngles(Angle(2.007624, -1.220685, 0.000000)) --UPTOWN
  653.     --tel:SetAngles(Angle(0.160586, -90.368736, 0.000000)) --DOWNTOWN
  654.     tel:Spawn()
  655.     --[[
  656.     local tel = ents.Create("npc_refiner")
  657.     tel:SetPos( GetNamedSpawn("refiner") )
  658.     tel:SetAngles(Angle(0,90,0))
  659.     tel:Spawn()
  660.     ]]
  661.     local tel = ents.Create("npc_pothead")
  662.     tel:SetPos(GetNamedSpawn("pothead"))
  663.     tel:SetAngles(Angle(1.445511, -134.679184, 0.000000)) --UPTOWN
  664.     --tel:SetAngles(Angle(-2.007504, 3.501955, 0.000000)) --DOWNTOWN
  665.     tel:Spawn()
  666.     local tel = ents.Create("npc_pothead")
  667.     tel:SetPos(GetNamedSpawn("smackhead"))
  668.     tel:SetAngles(Angle(0.240853, 178.907089, 0.000000)) --UPTOWN
  669.     --tel:SetAngles(Angle(-2.007504, 3.501955, 0.000000)) --DOWNTOWN
  670.     tel:Spawn()
  671. end
  672.  
  673. hook.Add("InitPostEntity", "GangEntInit", GangInitTerritories)
  674.  
  675. -- Handle gang rivalry kills
  676. local function GangRivalryDeath(victim, weapon, killer)
  677.     -- if the killer is on a mass murder mission, cancel all affects & knock out
  678.     if IsValid(victim) and IsValid(killer) and killer.MissionKills then return end
  679.  
  680.     if victim:IsPlayer() and killer:IsPlayer() and killer ~= victim and GangWars.GetLevel(victim) >= 10 then
  681.         local vgang = victim:GetNW2String("gang_name")
  682.         local kgang = killer:GetNW2String("gang_name")
  683.         if vgang == "" or kgang == "" then return end
  684.  
  685.         -- see if there is a rivalry between killer and victim
  686.         isql:QueryValue("SELECT COUNT(*) FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(kgang) .. " AND `rival` = " .. isql:Escape(vgang) .. ";", function(v)
  687.             if not v or tonumber(v) < 1 then return end
  688.             -- calculate the fine the other gang will pay
  689.             local vlvl = GangWars.GetLevel(victim) / 2
  690.             local fine = (vlvl * vlvl) * 10
  691.  
  692.             -- upgrade adds to the fine
  693.             if killer.GangInfo then
  694.                 if killer.GangInfo.rivalboost and killer.GangInfo.rivalboost > 0 then
  695.                     local txt, aff = Gang.GetUpgradeEffect("rivalboost", killer.GangInfo.rivalboost - 1)
  696.                     fine = fine + math.floor((fine / 100) * aff)
  697.                 end
  698.             end
  699.  
  700.             fine = math.floor(fine)
  701.  
  702.             --[[
  703.             // add cash to gang stash
  704.             // !!!!!!!!!!!!!!!
  705.             local stashes = ents.FindByClass("gang_stash")
  706.             if stashes then
  707.                 for k,v in pairs(stashes) do
  708.                     if v.gang == kgang then
  709.                         v:AddMoney() // adds % to stash
  710.                     end
  711.                 end
  712.             end
  713.             // !!!!!!!!!!!!!!!!!!!!
  714.             ]]
  715.             -- check they can afford it
  716.             GangWars.DB.GangCanAfford(vgang, fine, function(canafford)
  717.                 if canafford then
  718.                     -- fine the gang
  719.                     GangWars.DB.AddGangMoney(vgang, -fine, function()
  720.                         NotifyGang(vgang, 4, 4, "Gang lost " .. CUR .. GangWars.FormatMoney(fine) .. " when " .. victim:Nick() .. " died")
  721.                         NotifyGang(kgang, 4, 4, "Gang gained " .. CUR .. GangWars.FormatMoney(fine) .. " for killing " .. victim:Nick())
  722.                         -- update rivalry stats
  723.                         isql:Query("UPDATE `gw_gang_rivals` SET `members_killed` = `members_killed` + 1 WHERE `gang` = " .. isql:Escape(kgang) .. " AND `rival` = " .. isql:Escape(vgang) .. ";")
  724.                         isql:Query("UPDATE `gw_gang_rivals` SET `members_lost` = `members_lost` + 1 WHERE `gang` = " .. isql:Escape(vgang) .. " AND `rival` = " .. isql:Escape(kgang) .. ";")
  725.  
  726.                         -- log
  727.                         if IsValid(killer) then
  728.                             GangWars.GangLog(kgang, IsValid(victim) and victim:Nick() or "unknown", "KillRival", killer)
  729.                         end
  730.  
  731.                         -- add XP and money
  732.                         GangWars.DB.AddGangMoney(kgang, fine)
  733.                         GangWars.DB.AddGangXP(kgang, fine / 10)
  734.                     end)
  735.                 else
  736.                     -- force the bankrupt gang to lose
  737.                     GangWars.DB.RivalryWin(kgang, vgang)
  738.                 end
  739.             end)
  740.         end)
  741.     end
  742. end
  743.  
  744. hook.Add("PlayerDeath", "GangRivalryDeath", GangRivalryDeath)
  745.  
  746. --////////////////////////////////////////////////////////////////////////////
  747. -- Database
  748. local function ValidSteam(ply)
  749.     if not IsValid(ply) then return end
  750.     local steamID = ply:SteamID()
  751.     --if steamID == "STEAM_ID_PENDING" or steamID == "STEAM_ID_UNKNOWN" or steamID == "UNKNOWN" or steamID == "PENDING" then
  752.     --  return
  753.     --end
  754.  
  755.     return steamID
  756. end
  757.  
  758. -- gets the name of the gang a player is in
  759. function GangWars.DB.GetPlayerGang(ply, func, show_invites)
  760.     local steamID = ""
  761.  
  762.     if type(ply) == "string" then
  763.         steamID = ply
  764.     else
  765.         steamID = ValidSteam(ply)
  766.     end
  767.  
  768.     if not steamID then
  769.         func(nil, "Invalid STEAMID")
  770.  
  771.         return
  772.     end
  773.  
  774.     if show_invites then
  775.         isql:QueryValue("SELECT `gang` FROM `gw_gang_members` WHERE `steam` = " .. isql:Escape(steamID) .. ";", function(r)
  776.             if r then
  777.                 func(tostring(r))
  778.             else
  779.                 func(nil)
  780.             end
  781.         end)
  782.     else
  783.         isql:QueryValue("SELECT `gang` FROM `gw_gang_members` WHERE `steam` = " .. isql:Escape(steamID) .. " AND `rank` < 6;", function(r)
  784.             if r then
  785.                 func(tostring(r))
  786.             else
  787.                 func(nil)
  788.             end
  789.         end)
  790.     end
  791. end
  792.  
  793. -- gets a players rank within their gang
  794. function GangWars.DB.GetPlayerGangRank(ply, func)
  795.     local steamID = ""
  796.  
  797.     if type(ply) == "string" then
  798.         steamID = ply
  799.     else
  800.         steamID = ValidSteam(ply)
  801.     end
  802.  
  803.     if not steamID then
  804.         func(nil, "Invalid STEAMID")
  805.  
  806.         return
  807.     end
  808.  
  809.     isql:QueryValue("SELECT `rank` FROM `gw_gang_members` WHERE `steam` = " .. isql:Escape(steamID) .. " AND `rank` < 6;", function(r)
  810.         if r then
  811.             func(tonumber(r))
  812.         else
  813.             func(nil)
  814.  
  815.             return
  816.         end
  817.     end)
  818. end
  819.  
  820. -- returns gang name, xp, level, money
  821. function GangWars.DB.GetPlayerGangInfo(ply, func)
  822.     local steamID = ""
  823.  
  824.     if type(ply) == "string" then
  825.         steamID = ply
  826.     else
  827.         steamID = ValidSteam(ply)
  828.     end
  829.  
  830.     if not steamID then
  831.         func(nil, "Invalid STEAMID")
  832.  
  833.         return
  834.     end
  835.  
  836.     isql:QueryRow("SELECT * FROM `gw_gangs` INNER JOIN `gw_gang_members` ON gw_gang_members.gang = gw_gangs.name WHERE gw_gang_members.steam = " .. isql:Escape(steamID) .. ";", func)
  837. end
  838.  
  839. -- returns gang name, xp, level, money
  840. function GangWars.DB.GetGangInfo(gang_name, func)
  841.     isql:QueryRow("SELECT * FROM `gw_gangs` WHERE `name` = " .. isql:Escape(gang_name) .. ";", func)
  842. end
  843.  
  844. -- gets the list of members of a gang
  845. function GangWars.DB.GetGangStorage(gang_name, func)
  846.     isql:Query("SELECT * FROM `view_gang_storage` WHERE `gang` = " .. isql:Escape(gang_name) .. ";", func)
  847. end
  848.  
  849. -- gets the list of members of a gang
  850. function GangWars.DB.GetPlayerGangMemberList(gang_name, func)
  851.     isql:Query("SELECT `names`.`name` AS `name`, `members`.`rank` AS `rank`, `names`.`steam` AS `steam` FROM `gw_gang_members` `members` INNER JOIN `gw_characters` `names` ON `names`.`name` = `members`.`steam` WHERE `members`.`gang` = " .. isql:Escape(gang_name) .. ";", func)
  852. end
  853.  
  854. -- gets the list of members + stats in a gang. takes a unique ID for temp table
  855. function GangWars.DB.GetGangMemberStats(gang_name, uid, func)
  856.     local stats = {}
  857.     local q = "SELECT * FROM `gw_gang_members` WHERE `gang` = " .. isql:Escape(gang_name) .. ";"
  858.  
  859.     isql:Query(q, function(da, su, er)
  860.         if su then
  861.             for k, v in pairs(da or {}) do
  862.                 if not stats[v["steam"]] then
  863.                     stats[v["steam"]] = {}
  864.                     stats[v["steam"]]["rank"] = v["rank"]
  865.                     stats[v["steam"]]["money_donated"] = 0
  866.                     stats[v["steam"]]["money_earned"] = 0
  867.                     stats[v["steam"]]["money_spent"] = 0
  868.                     stats[v["steam"]]["xp_earned"] = 0
  869.                     stats[v["steam"]]["captures"] = 0
  870.                     stats[v["steam"]]["wars"] = 0
  871.                     stats[v["steam"]]["invites"] = 0
  872.                     stats[v["steam"]]["rivals"] = 0
  873.                 end
  874.             end
  875.         end
  876.  
  877.         q = "SELECT * FROM `gw_gang_log` WHERE `date` >= NOW() - INTERVAL 7 DAY and `gang` = " .. isql:Escape(gang_name) .. ";"
  878.  
  879.         isql:Query(q, function(d, s, e)
  880.             if s then
  881.                 for k, v in pairs(d or {}) do
  882.                     if not stats[v["member"]] then continue end
  883.                     if v["event"] == "Invite" then
  884.                         stats[v["member"]]["invites"] = stats[v["member"]]["invites"] + 1
  885.                     end
  886.  
  887.                     if v["event"] == "Donate" then
  888.                         stats[v["member"]]["money_donated"] = stats[v["member"]]["money_donated"] + v["number"]
  889.                     end
  890.  
  891.                     if v["event"] == "Buy" then
  892.                         stats[v["member"]]["money_spent"] = stats[v["member"]]["money_spent"] + v["number"]
  893.                     end
  894.  
  895.                     if v["event"] == "Upgrade" then
  896.                         stats[v["member"]]["money_spent"] = stats[v["member"]]["money_spent"] + v["number"]
  897.                     end
  898.  
  899.                     if v["event"] == "Print" then
  900.                         stats[v["member"]]["money_earned"] = stats[v["member"]]["money_earned"] + v["number"]
  901.                     end
  902.  
  903.                     if v["event"] == "XP" then
  904.                         stats[v["member"]]["xp_earned"] = stats[v["member"]]["xp_earned"] + v["number"]
  905.                     end
  906.  
  907.                     if v["event"] == "Capture" then
  908.                         stats[v["member"]]["captures"] = stats[v["member"]]["captures"] + 1
  909.                     end
  910.  
  911.                     if v["event"] == "War" then
  912.                         stats[v["member"]]["wars"] = stats[v["member"]]["wars"] + 1
  913.                     end
  914.  
  915.                     if v["event"] == "KillRival" then
  916.                         stats[v["member"]]["rivals"] = stats[v["member"]]["rivals"] + 1
  917.                     end
  918.                 end
  919.             end
  920.  
  921.             func(stats)
  922.         end)
  923.     end)
  924. end
  925.  
  926. -- gets the list of rivals of a gang
  927. function GangWars.DB.GetGangRivalList(gang_name, func)
  928.     isql:Query("SELECT g.name, g.logo, g.color, g.color2, g.level, riv.*, TIME_TO_SEC(TIMEDIFF(NOW(), riv.`started`))/60/60 AS `hours_left` FROM `gw_gang_rivals` riv INNER JOIN `gw_gangs` g ON g.name = riv.rival WHERE riv.gang = " .. isql:Escape(gang_name) .. ";", func)
  929. end
  930.  
  931. function GangWars.DB.CreateGang(ply, gang_name, gang_password, gang_logo, gang_color, gang_color2, func)
  932.     local steamID = ValidSteam(ply)
  933.  
  934.     if not steamID then
  935.         func(nil, "Invalid STEAMID")
  936.  
  937.         return
  938.     end
  939.  
  940.     -- reject bad gang names
  941.     local allowedCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:-1234567890 "
  942.  
  943.     for i = 1, string.len(gang_name) do
  944.         local ok = false
  945.  
  946.         for j = 1, string.len(allowedCharacters) do
  947.             if string.sub(gang_name, i, i) == string.sub(allowedCharacters, j, j) then
  948.                 ok = true
  949.                 break
  950.             end
  951.         end
  952.  
  953.         if not ok then
  954.             func(nil, "Gang name contains illegal symbol at character #" .. i)
  955.  
  956.             return
  957.         end
  958.     end
  959.  
  960.     -- verify time is ok
  961.     isql:QueryValue("SELECT TIME_TO_SEC(TIMEDIFF(NOW(), time)) FROM `gw_time` WHERE name = " .. isql:Escape("gang_create_" .. ply:RealSteamID()) .. ";", function(time)
  962.         if time and tonumber(time) < 86400 then
  963.             func(nil, "You can only make 1 gang per day")
  964.  
  965.             return
  966.         end
  967.  
  968.         isql:Query("UPDATE `gw_time` SET `time` = NOW() WHERE name = " .. isql:Escape("gang_create_" .. ply:RealSteamID()) .. ";", function(d, s, err)
  969.             -- check gang name doesn't exist
  970.             isql:QueryValue("SELECT * FROM gw_gangs WHERE name = " .. isql:Escape(gang_name) .. ";", function(r)
  971.                 if r then
  972.                     func(nil, "Gang already exists!")
  973.  
  974.                     return
  975.                 end
  976.  
  977.                 -- check we're not already in a gang
  978.                 local g = GangWars.DB.GetPlayerGang(ply, function(g)
  979.                     if g and g ~= "" then
  980.                         func(nil, "You are already in a gang")
  981.  
  982.                         return
  983.                     end
  984.  
  985.                     -- delete any old invites we had
  986.                     isql:Query("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. ";", function()
  987.                         -- create gang
  988.                         isql:Query("INSERT INTO gw_gangs (`name`, `password`, `logo`, `color`, `color2`, `level`, `xp`, `money`, `creator`, `last_base`) VALUES(" .. isql:Escape(gang_name) .. ", " .. isql:Escape(gang_password) .. ", " .. isql:Escape(gang_logo) .. ", '" .. isql:Escape(gang_color.r) .. " " .. isql:Escape(gang_color.g) .. " " .. isql:Escape(gang_color.b) .. "', '" .. isql:Escape(gang_color2.r) .. " " .. isql:Escape(gang_color2.g) .. " " .. isql:Escape(gang_color2.b) .. "', 1, 0, 0, " .. isql:Escape(steamID) .. ", NOW());", function()
  989.                             -- and owner
  990.                             isql:Query("INSERT INTO gw_gang_members (`gang`, `steam`, `rank`) VALUES(" .. isql:Escape(gang_name) .. ", " .. isql:Escape(steamID) .. ", 1);", function()
  991.                                 func(true)
  992.                                 net.Start("sv_refresh_topgangs")
  993.                                 net.Broadcast()
  994.                             end)
  995.                         end)
  996.                     end)
  997.                 end)
  998.             end)
  999.         end)
  1000.     end)
  1001. end
  1002.  
  1003. function GangWars.DB.SetPlayerGangRank(ply, gang, rank, func)
  1004.     local steamID = ""
  1005.  
  1006.     if type(ply) == "string" then
  1007.         steamID = ply
  1008.     else
  1009.         steamID = ValidSteam(ply)
  1010.     end
  1011.  
  1012.     if not steamID then
  1013.         func(nil, "Invalid STEAMID")
  1014.  
  1015.         return
  1016.     end
  1017.  
  1018.     if rank < 1 or rank > 5 then
  1019.         func(nil, nil)
  1020.  
  1021.         return
  1022.     end
  1023.  
  1024.     isql:Query("UPDATE gw_gang_members SET `rank`= " .. isql:Escape(rank) .. " WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(gang) .. ";", function()
  1025.         func(true)
  1026.     end)
  1027. end
  1028.  
  1029. function GangWars.DB.GetGangMemberLimit(gang_name, func)
  1030.     func(10)
  1031.     --[[
  1032.     // check gang hasn't reached its member limit
  1033.     isql:Query("SELECT `level`, `boost_members` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) ..";",
  1034.     function(glevel)
  1035.         if not glevel then
  1036.             func()
  1037.             return
  1038.         end
  1039.         glevel = tonumber(glevel.level)
  1040.         local members = tonumber(glevel.boost_members)
  1041.  
  1042.         func( Gang.GetMemberLimit(glevel) + members )
  1043.     end)
  1044.     ]]
  1045. end
  1046.  
  1047. function GangWars.DB.InviteToGang(ply, gang_name, func)
  1048.     local steamID = ValidSteam(ply)
  1049.  
  1050.     if not steamID then
  1051.         func(nil, "Invalid STEAMID")
  1052.  
  1053.         return
  1054.     end
  1055.  
  1056.     -- check they aren't in a gang
  1057.     isql:QueryValue("SELECT * FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. " AND `rank` < 6;", function(r)
  1058.         if r then
  1059.             func(nil, "Player is already in another gang")
  1060.  
  1061.             return
  1062.         end
  1063.  
  1064.         -- check gang hasn't reached its member limit
  1065.         isql:QueryRow("SELECT `level`, `memberboost` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(glevel)
  1066.             if not glevel then
  1067.                 func(nil, "Couldn't find gang level or member boost")
  1068.  
  1069.                 return
  1070.             end
  1071.  
  1072.             local members = 10 --(tonumber(glevel.memberboost)) + Gang.GetMemberLimit(tonumber(glevel.level))
  1073.             glevel = tonumber(glevel.level)
  1074.  
  1075.             isql:QueryValue("SELECT COUNT(*) FROM gw_gang_members WHERE `gang` = " .. isql:Escape(gang_name) .. ";", function(mcount)
  1076.                 mcount = tonumber(mcount)
  1077.  
  1078.                 if not glevel or not mcount or mcount >= members then
  1079.                     func(nil, "Your gang has reached its member limit! (Max " .. members .. " members)")
  1080.  
  1081.                     return
  1082.                 end
  1083.  
  1084.                 -- add them with invited rank
  1085.                 isql:Query("INSERT INTO gw_gang_members (`gang`, `steam`, `rank`) VALUES(" .. isql:Escape(gang_name) .. ", " .. isql:Escape(steamID) .. ", 6);", function()
  1086.                     func(true)
  1087.                 end)
  1088.             end)
  1089.         end)
  1090.     end)
  1091. end
  1092.  
  1093. function GangWars.DB.AcceptInvite(ply, gang, func)
  1094.     local steamID = ValidSteam(ply)
  1095.  
  1096.     if not steamID then
  1097.         func(nil, "Invalid STEAMID")
  1098.  
  1099.         return
  1100.     end
  1101.  
  1102.     -- check they are being invited to the gang
  1103.     isql:QueryValue("SELECT `rank` FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(gang) .. ";", function(r)
  1104.         if not r or tonumber(r) ~= 6 then
  1105.             func(nil, "Not invited to that gang!")
  1106.  
  1107.             return
  1108.         end
  1109.  
  1110.         -- add them with basic rank
  1111.         isql:Query("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` != " .. isql:Escape(gang) .. ";", function()
  1112.             -- add them with basic rank
  1113.             isql:Query("UPDATE gw_gang_members SET `rank` = '5' WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(gang) .. ";", function()
  1114.                 func(true)
  1115.             end)
  1116.         end)
  1117.     end)
  1118. end
  1119.  
  1120. function GangWars.DB.RejectInvite(ply, gang, func)
  1121.     local steamID = ValidSteam(ply)
  1122.  
  1123.     if not steamID then
  1124.         func(nil, "Invalid STEAMID")
  1125.  
  1126.         return
  1127.     end
  1128.  
  1129.     -- check they are being invited to the gang
  1130.     isql:QueryValue("SELECT `rank` FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(gang) .. ";", function(r)
  1131.         if not r or tonumber(r) ~= 6 then
  1132.             func(nil, "Not invited to that gang!")
  1133.  
  1134.             return
  1135.         end
  1136.  
  1137.         -- remove invite
  1138.         isql:Query("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(gang) .. ";", function()
  1139.             func(true)
  1140.         end)
  1141.     end)
  1142. end
  1143.  
  1144. function GangWars.DB.RemoveFromGangBySteam(steam, gang, func)
  1145.     isql:QueryRow("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steam) .. " AND `gang` = " .. isql:Escape(gang) .. ";", func)
  1146. end
  1147.  
  1148. function GangWars.DB.RemoveFromGangByName(ply_name, gang, func)
  1149.     -- find the player
  1150.     isql:QueryRow("SELECT n.name, n.steam, g.gang, g.rank FROM gw_characters n INNER JOIN gw_gang_members g ON g.steam = n.name WHERE n.name LIKE " .. isql:Escape(ply_name) .. ";", function(query)
  1151.         if not query or not query.name then
  1152.             func(nil, "Can't find target players name")
  1153.  
  1154.             return
  1155.         end
  1156.  
  1157.         local steamID = query.steam
  1158.  
  1159.         if not steamID or steamID == "" then
  1160.             func(nil, "Can't find target players steamID")
  1161.  
  1162.             return
  1163.         end
  1164.  
  1165.         local gang_name = query.gang
  1166.  
  1167.         if not gang_name or gang_name == "" or gang_name ~= gang then
  1168.             func(nil, "Can't find target players gang")
  1169.  
  1170.             return
  1171.         end
  1172.  
  1173.         -- remove them
  1174.         isql:Query("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. ";", function()
  1175.             func(true)
  1176.         end)
  1177.     end)
  1178.     -- if they were owner, delete gang & all members
  1179.     --if tonumber(rank) == 1 then
  1180.     --  isql:Query("DELETE FROM gw_gang_members WHERE `gang` = " .. isql:Escape(gang_name) .. ";")
  1181.     --  isql:Query("DELETE FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";")
  1182.     --end
  1183. end
  1184.  
  1185. function GangWars.DB.RemoveFromGang(ply, func)
  1186.     local steamID = ValidSteam(ply)
  1187.  
  1188.     if not steamID then
  1189.         func(nil, "Invalid STEAMID")
  1190.  
  1191.         return
  1192.     end
  1193.  
  1194.     local gang_name = GangWars.DB.GetPlayerGang(ply, function(gang_name)
  1195.         if not gang_name then
  1196.             func(nil, "Couldn't find gang")
  1197.  
  1198.             return
  1199.         end
  1200.  
  1201.         -- remove them
  1202.         isql:Query("DELETE FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. ";", function()
  1203.             func(true)
  1204.             net.Start("sv_refresh_topgangs")
  1205.             net.Broadcast()
  1206.         end)
  1207.     end)
  1208.     -- if they were owner, delete gang & all members
  1209.     --if tonumber(rank) == 1 then
  1210.     --  isql:Query("DELETE FROM gw_gang_members WHERE gang = " .. isql:Escape(gang_name) .. ";")
  1211.     --  isql:Query("DELETE FROM gw_gangs WHERE name = " .. isql:Escape(gang_name) .. ";")
  1212.     --end
  1213. end
  1214.  
  1215. function GangWars.DB.RivalryWin(winner, loser, ignoretruce, supressmessage)
  1216.     local args = loser
  1217.     local gang = winner
  1218.  
  1219.     -- see if other gang is our rival
  1220.     isql:QueryValue("SELECT COUNT(*) FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang) .. ";", function(truce)
  1221.         if (not truce or tonumber(truce) <= 0) and not ignoretruce then return end --GangNotify(ply, 3, 4, "You don't seem to have a rivalry with " .. args)
  1222.  
  1223.         -- remove the rivalry
  1224.         isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(gang) .. " AND `rival` = " .. isql:Escape(args) .. ";", function()
  1225.             isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang) .. ";", function()
  1226.                 --MsgN("Deleted rivalry entires")
  1227.                 isql:QueryValue("SELECT `points` FROM `gw_gangs` WHERE `name` = " .. isql:Escape(args) .. ";", function(loser_points)
  1228.                     -- find level difference
  1229.                     --isql:QueryValue("SELECT `level` FROM `gw_gangs` WHERE `name` = " .. isql:Escape(gang) .. ";",
  1230.                     --function(my_level)
  1231.                     --isql:QueryValue("SELECT `level` FROM `gw_gangs` WHERE `name` = " .. isql:Escape(args) .. ";",
  1232.                     --function(their_level)
  1233.                     --[[
  1234.                         if not their_level then
  1235.                             Msg("WARNING: " .. loser .. " requested mercy but can't find level for them\n")
  1236.                         end
  1237.                         if not my_level then
  1238.                             Msg("WARNING: " .. loser .. " requested mercy but can't find level for " .. winner .. "\n")
  1239.                         end
  1240.                         if not their_level or not my_level then
  1241.                             return
  1242.                         end
  1243.  
  1244.                         MsgN("Awarding points")
  1245.  
  1246.                         // find level difference
  1247.                         local lvl_diff = their_level - my_level
  1248.  
  1249.                         // find points
  1250.                         local points = math.max(10000 + (1000 * lvl_diff), 0)
  1251.                         ]]
  1252.                     local points = math.floor(loser_points / 5)
  1253.                     -- award points
  1254.                     GangWars.DB.AddGangPoints(gang, points, function() end)
  1255.                     GangWars.DB.AddGangPoints(args, -points, function() end)
  1256.  
  1257.                     -- refresh their view
  1258.                     if not supressmessage then
  1259.                         NotifyGang(gang, 4, 4, "You gained " .. points .. " points for defeating " .. args)
  1260.                         NotifyGang(args, 4, 4, "You have lost the fight with " .. gang .. " and lost " .. points .. " points")
  1261.                     end
  1262.  
  1263.                     for k, v in pairs(player.GetAll()) do
  1264.                         if IsValid(v) then
  1265.                             if v:Gang() == gang or v:Gang() == args then
  1266.                                 InitPlayerGang(v)
  1267.                             end
  1268.                         end
  1269.                     end
  1270.  
  1271.                     -- add norivalry entry (5 days)
  1272.                     -- Modified 03-10-2012 to block the spammy abuse of mercy to increase gang points
  1273.                     isql:Query("INSERT INTO `gw_gang_norival` (`gang`, `rival`, `expires`) VALUES (" .. isql:Escape(gang) .. ", " .. isql:Escape(args) .. ", DATE_ADD(NOW(), INTERVAL 5 DAY));")
  1274.                     -- add norivalry entry for the loser (1 day, to prevent spam)
  1275.                     isql:Query("INSERT INTO `gw_gang_norival` (`gang`, `rival`, `expires`) VALUES (" .. isql:Escape(args) .. ", " .. isql:Escape(gang) .. ", DATE_ADD(NOW(), INTERVAL 1 DAY));")
  1276.                 end)
  1277.             end)
  1278.         end)
  1279.     end)
  1280.     --end)
  1281. end
  1282.  
  1283. -- adds to a gangs XP
  1284. function GangWars.DB.AddGangXP(gang_name, add_xp)
  1285.     if not gang_name or gang_name == "" then return end
  1286.  
  1287.     -- find the gangs xp & level
  1288.     isql:QueryRow("SELECT `xp`, `level`, `gangxpboost` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(r)
  1289.         if not r then return end
  1290.         local xp = tonumber(r['xp'])
  1291.         local level = tonumber(r['level'])
  1292.         local boost = tonumber(r['gangxpboost'])
  1293.         if level >= 20 then return end
  1294.  
  1295.         -- boost XP
  1296.         if boost and boost > 0 then
  1297.             local txt, aff = Gang.GetUpgradeEffect("missionboost", boost - 1)
  1298.             add_xp = add_xp + math.floor((add_xp / 100) * aff)
  1299.         end
  1300.  
  1301.         -- add the XP
  1302.         xp = xp + add_xp
  1303.         local levelup = false
  1304.  
  1305.         -- level up gang
  1306.         if xp > Gang.XP2Level(level) then
  1307.             levelup = true
  1308.             isql:Query("UPDATE gw_gangs SET `xp` = 0, `level` = " .. (level + 1) .. " WHERE `name` = " .. isql:Escape(gang_name) .. ";")
  1309.         else
  1310.             isql:Query("UPDATE gw_gangs SET `xp` = `xp` + '" .. add_xp .. "' WHERE `name` = " .. isql:Escape(gang_name) .. ";")
  1311.         end
  1312.     end)
  1313. end
  1314.  
  1315. -- adds to a gangs money
  1316. function GangWars.DB.AddGangMoney(gang_name, money, func)
  1317.     if not gang_name or gang_name == "" then
  1318.         if func then
  1319.             func(nil)
  1320.         end
  1321.  
  1322.         return
  1323.     end
  1324.  
  1325.     isql:Query("UPDATE gw_gangs SET `money` = `money` + " .. isql:Escape(tonumber(money)) .. " WHERE `name` = " .. isql:Escape(gang_name) .. ";", func)
  1326. end
  1327.  
  1328. -- adds to a gangs points
  1329. function GangWars.DB.AddGangPoints(gang_name, points, func)
  1330.     if not gang_name or gang_name == "" then
  1331.         if func then
  1332.             func(nil)
  1333.         end
  1334.  
  1335.         return
  1336.     end
  1337.  
  1338.     if GangWars.EventActive("doublexp") or GangWars.EventActive("doublepoints") then
  1339.         points = points * 2
  1340.     end
  1341.  
  1342.     isql:Query("UPDATE gw_gangs SET `points` = `points` + " .. isql:Escape(tonumber(points)) .. " WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(d)
  1343.         -- auto update clients in the gang of their points
  1344.         GangWars.DB.GetGangPoints(gang_name, function(gp)
  1345.             for k, v in pairs(player.GetAll()) do
  1346.                 if gp and v:Gang() == gang_name then
  1347.                     net.Start("ds_gang_points")
  1348.                     net.WriteInt(gp, 32)
  1349.                     net.Send(v)
  1350.                 end
  1351.             end
  1352.         end)
  1353.  
  1354.         -- callback
  1355.         if func then
  1356.             func(d)
  1357.         end
  1358.     end)
  1359. end
  1360.  
  1361. -- fetch a gangs points
  1362. function GangWars.DB.GetGangPoints(gang_name, func)
  1363.     if not gang_name or gang_name == "" then
  1364.         if func then
  1365.             func(nil)
  1366.         end
  1367.  
  1368.         return
  1369.     end
  1370.  
  1371.     isql:QueryValue("SELECT `points` FROM `gw_gangs` WHERE `name` = " .. isql:Escape(gang_name) .. ";", func)
  1372. end
  1373.  
  1374. -- checks gang money
  1375. function GangWars.DB.GangCanAfford(gang_name, money, func)
  1376.     if not gang_name or gang_name == "" then return end
  1377.  
  1378.     isql:QueryValue("SELECT `money` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(mon)
  1379.         if mon and tonumber(mon) >= money then
  1380.             func(true)
  1381.         else
  1382.             func(false)
  1383.         end
  1384.     end)
  1385. end
  1386.  
  1387. -- upgrades a gang
  1388. function GangWars.DB.GangUpgrade(gang_name, upgrade, func)
  1389.     if not gang_name or gang_name == "" then
  1390.         func(nil, nil)
  1391.  
  1392.         return
  1393.     end
  1394.  
  1395.     -- check the sql input!
  1396.     if upgrade ~= "hpboost" and upgrade ~= "regen" and upgrade ~= "extraitems" and upgrade ~= "xpboost" and upgrade ~= "speedboost" and upgrade ~= "printboost" and upgrade ~= "drugboost" and upgrade ~= "dropboost" and upgrade ~= "armorboost" and upgrade ~= "memberboost" and upgrade ~= "shopboost" and upgrade ~= "ppocketboost" and upgrade ~= "bankboost" and upgrade ~= "missionboost" and upgrade ~= "gangxpboost" then
  1397.         func(nil, "Invalid upgrade")
  1398.  
  1399.         return
  1400.     end
  1401.  
  1402.     -- find the upgrade level
  1403.     isql:QueryValue("SELECT `" .. upgrade .. "` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(ulevel)
  1404.         ulevel = tonumber(ulevel)
  1405.  
  1406.         if not ulevel or ulevel >= 10 then
  1407.             func(nil, "This is already fully upgraded")
  1408.  
  1409.             return
  1410.         end
  1411.  
  1412.         -- find the gangs money
  1413.         isql:QueryRow("SELECT `money`, `level` FROM gw_gangs WHERE `name` = " .. isql:Escape(gang_name) .. ";", function(r)
  1414.             if not r then
  1415.                 func(nil, "Can't find your gang?")
  1416.  
  1417.                 return
  1418.             end
  1419.  
  1420.             local amt = tonumber(r['money'])
  1421.             local glevel = tonumber(r['level'])
  1422.  
  1423.             -- check gang is high enough level
  1424.             if glevel <= ulevel then
  1425.                 func(nil, "Gang isn't high enough level", amt)
  1426.  
  1427.                 return
  1428.             end
  1429.  
  1430.             -- find upgrade cost
  1431.             local price = Gang.GetUpgradePrice(ulevel)
  1432.  
  1433.             -- check we can afford it
  1434.             if amt < price then
  1435.                 func(nil, "Gang can't afford that", amt)
  1436.  
  1437.                 return
  1438.             end
  1439.  
  1440.             -- charge the team
  1441.             amt = amt - price
  1442.  
  1443.             -- save and upgrade
  1444.             isql:Query("UPDATE gw_gangs SET `money` = " .. amt .. ", `" .. upgrade .. "` = " .. (ulevel + 1) .. " WHERE `name` = " .. isql:Escape(gang_name) .. ";", function()
  1445.                 func(true, "", amt)
  1446.             end)
  1447.         end)
  1448.     end)
  1449. end
  1450.  
  1451. --////////////////////////////////////////////////////////////////////////////
  1452. -- Commands
  1453. -- change logo
  1454. local function GC_ChangeLogo(len, ply)
  1455.     local decoded = net.ReadTable()
  1456.     if not decoded or not decoded.logo then return end
  1457.     if decoded.logo < 1 then return end
  1458.     if decoded.logo > 30 then return end
  1459.     local gname = "extra/" .. decoded.logo
  1460.     --[[
  1461.     if not string.find(gname, "extra") then
  1462.         GangNotify(ply, 3, 4, "Invalid logo... you've been logged, thank you!")
  1463.         GangWars.Log("cheat", ply, ply:Nick() .. " tried to set gang logo to '" .. gname .. "'")
  1464.         return
  1465.     end
  1466.     ]]
  1467.     local steamID = ValidSteam(ply)
  1468.     if not steamID then return end
  1469.     local gang = ply:GetNW2String("gang_name")
  1470.  
  1471.     -- find gang info
  1472.     GangWars.DB.GetGangInfo(gang, function(info)
  1473.         if not info then
  1474.             Msg("GC_ChangeLogo: GangWars.DB.GetGangInfo returned nil")
  1475.  
  1476.             return
  1477.         end
  1478.  
  1479.         -- find our rank
  1480.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1481.             if not my_rank or tonumber(my_rank) > 1 then
  1482.                 GangNotify(ply, 3, 4, "Only leaders can buy logos")
  1483.  
  1484.                 return
  1485.             end
  1486.  
  1487.             local gangmoney = tonumber(info.money)
  1488.             local ganglevel = tonumber(info.level)
  1489.             local logoprice = 500000 + tonumber(decoded.logo) * 200000
  1490.             --local logolevel = 5 + math.floor(tonumber(decoded.logo) / 10) * 5
  1491.             local logolevel = math.min(10 + math.floor(tonumber(decoded.logo) / 10) * 5, 20)
  1492.  
  1493.             -- abandon if we're not high enough level
  1494.             if logolevel > ganglevel then
  1495.                 GangNotify(ply, 3, 4, "Your gang must be level " .. logolevel .. " to buy that logo!")
  1496.  
  1497.                 return
  1498.             end
  1499.  
  1500.             -- abandon if we can't afford it
  1501.             if gangmoney < logoprice then
  1502.                 GangNotify(ply, 1, 4, "Your gang can not afford this logo!")
  1503.  
  1504.                 return
  1505.             end
  1506.  
  1507.             -- charge gang
  1508.             GangWars.DB.AddGangMoney(gang, -logoprice, function()
  1509.                 -- create gang
  1510.                 isql:Query("UPDATE gw_gangs SET `logo` = " .. isql:Escape(gname) .. " WHERE `name` = " .. isql:Escape(info.name) .. ";", function()
  1511.                     GangNotify(ply, 3, 4, "You successfully changed your gangs logo!")
  1512.                     GangWars.GangLog(gang, ply:Nick() .. " changed the gang logo", "Logo Change", ply)
  1513.                     InitPlayerGang(ply)
  1514.                 end)
  1515.             end)
  1516.         end)
  1517.     end)
  1518. end
  1519.  
  1520. net.Receive("ChangeGangLogo", GC_ChangeLogo)
  1521.  
  1522. -- change password
  1523. local function GC_ChangePassword(len, ply)
  1524.     local decoded = net.ReadTable()
  1525.     local steamID = ValidSteam(ply)
  1526.     if not steamID then return end
  1527.     if decoded and not decoded.old or not decoded.new then return end
  1528.  
  1529.     -- find ranks
  1530.     GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1531.         if not my_rank or my_rank ~= 1 then
  1532.             GangNotify(ply, 3, 4, "You must be gang leader to change the password")
  1533.  
  1534.             return
  1535.         end
  1536.  
  1537.         -- find gang info
  1538.         GangWars.DB.GetGangInfo(ply:GetNW2String("gang_name"), function(info)
  1539.             if not info then
  1540.                 Msg("GC_ChangePassword: GangWars.DB.GetGangInfo returned nil")
  1541.  
  1542.                 return
  1543.             end
  1544.  
  1545.             local gangpass = info.password
  1546.  
  1547.             -- abandon if old password does not match
  1548.             if tostring(gangpass) ~= tostring(util.CRC(decoded.old)) then
  1549.                 GangNotify(ply, 3, 4, "Old password was incorrect!")
  1550.  
  1551.                 return
  1552.             end
  1553.  
  1554.             -- charge gang
  1555.             --GangWars.DB.AddGangMoney(gang, -500000,
  1556.             --function()
  1557.             -- create gang
  1558.             isql:Query("UPDATE gw_gangs SET `password` = " .. isql:Escape(util.CRC(decoded.new)) .. " WHERE `name` = " .. isql:Escape(info.name) .. ";", function()
  1559.                 GangNotify(ply, 3, 4, "You successfully changed your gangs password!")
  1560.                 GangWars.GangLog(gang, ply:Nick() .. " changed the gang password", "Password Change", ply)
  1561.             end)
  1562.         end)
  1563.     end)
  1564.     --end)
  1565. end
  1566.  
  1567. net.Receive("ChangeGangPassword", GC_ChangePassword)
  1568.  
  1569. -- recover gang
  1570. local function GC_Recover(len, ply)
  1571.     local decoded = net.ReadTable()
  1572.     local steamID = ValidSteam(ply)
  1573.     if not steamID then return end
  1574.     if decoded and not decoded.name or not decoded.password then return end
  1575.  
  1576.     -- find gang info
  1577.     GangWars.DB.GetGangInfo(decoded.name, function(info)
  1578.         if not info then
  1579.             Msg("GC_Recover: GangWars.DB.GetGangInfo returned nil")
  1580.  
  1581.             return
  1582.         end
  1583.  
  1584.         local gangpass = info.password
  1585.  
  1586.         -- abandon if old password does not match
  1587.         if tostring(gangpass) ~= tostring(util.CRC(decoded.password)) then
  1588.             GangNotify(ply, 3, 4, "The password was incorrect! This action has been logged and sent to the admin team.")
  1589.             GangWars.Log("gang_recover", ply, ply:Nick() .. " tried to recover the gang '" .. decoded.name .. "' with a bad password")
  1590.  
  1591.             return
  1592.         end
  1593.  
  1594.         -- Remove all members. Set us as the only member/leader.
  1595.         isql:QueryValue("SELECT COUNT(*) FROM `gw_gang_members` WHERE `gang` = " .. isql:Escape(info.name) .. " AND `rank` = 1;", function(row)
  1596.             if tonumber(row) and tonumber(row) > 0 then
  1597.                 GangNotify(ply, 3, 4, "The gang already has a leader! This action has been logged and sent to the admin team.")
  1598.                 GangWars.Log("gang_recover", ply, ply:Nick() .. " tried to recover the gang '" .. decoded.name .. "' but it already has a leader")
  1599.  
  1600.                 return
  1601.             end
  1602.  
  1603.             -- create gang
  1604.             isql:Query("INSERT INTO `gw_gang_members` (`steam`, `gang`, `rank`) VALUES(" .. isql:Escape(steamID) .. ", " .. isql:Escape(info.name) .. ", 1);", function()
  1605.                 InitPlayerGang(ply)
  1606.                 ply:GangStorageRefresh()
  1607.                 GangNotify(ply, 3, 4, "You successfully recovered the " .. info.name .. " gang!")
  1608.                 GangWars.Log("gang_recover", ply, ply:Nick() .. " successfully recovered the gang '" .. decoded.name .. "'")
  1609.             end)
  1610.         end)
  1611.     end)
  1612. end
  1613.  
  1614. net.Receive("RecoverGang", GC_Recover)
  1615.  
  1616. -- /create <gang name>
  1617. local function GC_Create(len, ply)
  1618.     local decoded = net.ReadTable()
  1619.     local gname = decoded.name
  1620.  
  1621.     if string.len(gname) > 20 then
  1622.         GangNotify(ply, 3, 4, "Gang name must not exceed 20 characters!")
  1623.  
  1624.         return ""
  1625.     end
  1626.  
  1627.     local price = 100000
  1628.  
  1629.     if GangWars.GetLevel(ply) >= 10 and ply:CanAfford(price) and tonumber(decoded.logo) <= 25 then
  1630.         GangWars.DB.CreateGang(ply, gname, decoded.password, decoded.logo, decoded.color, decoded.color2, function(q, msg)
  1631.             if q then
  1632.                 ply:AddMoney(-price, "Gang creation")
  1633.                 InitPlayerGang(ply)
  1634.                 ply:GangStorageRefresh()
  1635.                 GangNotify(ply, 3, 4, "Congratulations! You have started the " .. gname .. " gang!")
  1636.             else
  1637.                 if msg then
  1638.                     GangNotify(ply, 3, 4, "Could not create gang. " .. msg)
  1639.                 else
  1640.                     GangNotify(ply, 3, 4, "Could not create gang.")
  1641.                 end
  1642.             end
  1643.         end)
  1644.     else
  1645.         GangNotify(ply, 3, 4, "You must be level 10 and have " .. CUR .. "100,000 to create a gang")
  1646.     end
  1647. end
  1648.  
  1649. net.Receive("CreateGang", GC_Create)
  1650.  
  1651. -- /leave gang
  1652. local function GC_Leave(ply, args)
  1653.     -- find our gang name
  1654.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1655.         if not gang then return end
  1656.  
  1657.         GangWars.DB.RemoveFromGang(ply, function(q)
  1658.             --timer.Simple(1, function () InitPlayerGang(ply) end )
  1659.             --timer.Simple(1, function() UpdateClientGangInfo(gang) end)
  1660.             --timer.Simple(1, function() UpdateClientGangMembers(gang) end)
  1661.             if q then
  1662.                 ply.GangInfo = nil
  1663.                 GangNotify(ply, 3, 4, "You have left the " .. gang .. " gang")
  1664.                 GangWars.GangLog(gang, ply:Nick() .. " left the gang", "Leave", ply)
  1665.                 InitPlayerGang(ply)
  1666.             end
  1667.         end)
  1668.     end)
  1669.  
  1670.     return ""
  1671. end
  1672.  
  1673. AddChatCommand("/gang_leave", GC_Leave)
  1674.  
  1675. local function GC_Donate(ply, args)
  1676.     -- find our gang name
  1677.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1678.         if not gang then return "" end
  1679.         local money = math.floor(tonumber(args))
  1680.         if money <= 0 then return "" end
  1681.  
  1682.         if not ply:CanAfford(money) then
  1683.             GangNotify(ply, 4, 4, "You don't have that much to donate!")
  1684.  
  1685.             return ""
  1686.         end
  1687.  
  1688.         -- swap money
  1689.         GangWars.DB.AddGangMoney(gang, money, function()
  1690.             InitPlayerGang(ply)
  1691.             ply:AddMoney(-money, "Gang donation")
  1692.             GangWars.GangLogNumber(gang, money, "Donate", ply)
  1693.             GangNotify(ply, 3, 4, "You have donated " .. CUR .. GangWars.FormatMoney(money) .. " to your gang")
  1694.         end)
  1695.     end)
  1696.  
  1697.     return ""
  1698. end
  1699.  
  1700. AddChatCommand("/gang_donate", GC_Donate)
  1701.  
  1702. -- upgrade gang
  1703. local function GC_Upgrade(ply, args)
  1704.     -- find our gang name
  1705.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1706.         if not gang then return end
  1707.  
  1708.         -- find ranks
  1709.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1710.             if not my_rank or my_rank > 2 then
  1711.                 GangNotify(ply, 3, 4, "You must be at least vice leader to purchase upgrades")
  1712.  
  1713.                 return
  1714.             end
  1715.  
  1716.             -- do upgrade
  1717.             GangWars.DB.GangUpgrade(gang, args, function(q, msg, amnt)
  1718.                 if q then
  1719.                     --timer.Simple(2, function() UpdateClientGangInfo(gang) end)
  1720.                     InitPlayerGang(ply)
  1721.                     GangNotify(ply, 3, 4, "You have upgraded your gang")
  1722.                     GangWars.GangLogNumber(gang, amnt, "Upgrade", ply, ply:Nick() .. " upgraded " .. args .. " for $" .. string.Comma(amnt))
  1723.                 else
  1724.                     if msg then
  1725.                         GangNotify(ply, 3, 4, "You can't purchase that upgrade. " .. msg)
  1726.                     else
  1727.                         GangNotify(ply, 3, 4, "You can't purchase that upgrade")
  1728.                     end
  1729.                 end
  1730.             end)
  1731.         end)
  1732.     end)
  1733.  
  1734.     return ""
  1735. end
  1736.  
  1737. AddChatCommand("/gang_upgrade", GC_Upgrade)
  1738.  
  1739. -- /invite <player>
  1740. local function GC_Invite(ply, args)
  1741.     -- find our gang
  1742.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1743.         if not gang then
  1744.             GangNotify(ply, 3, 4, "You aren't in a gang!")
  1745.  
  1746.             return
  1747.         end
  1748.  
  1749.         -- find our target
  1750.         local target = FindPlayer(args)
  1751.  
  1752.         if not target then
  1753.             GangNotify(ply, 3, 4, "Can't find that player to invite")
  1754.  
  1755.             return ""
  1756.         end
  1757.  
  1758.         -- find ranks
  1759.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1760.             if not my_rank or my_rank > 2 then
  1761.                 GangNotify(ply, 3, 4, "You must be leader or vice leader to invite")
  1762.  
  1763.                 return ""
  1764.             end
  1765.  
  1766.             -- invite them
  1767.             GangWars.DB.InviteToGang(target, gang, function(q, msg)
  1768.                 if q then
  1769.                     --timer.Simple(2, function () InitPlayerGang(target) end )
  1770.                     --timer.Simple(2, function() UpdateClientGangInfo(gang) end)
  1771.                     --timer.Simple(2, function() UpdateClientGangMembers(gang) end)
  1772.                     unet.Start("gang_invite", target)
  1773.                     net.WriteString(gang)
  1774.                     unet.Send(target)
  1775.                     InitPlayerGang(ply)
  1776.                     InitPlayerGang(target)
  1777.                     GangWars.GangLog(gang, ply:Nick() .. " invited " .. target:Nick(), "Invite", ply)
  1778.                     GangNotify(ply, 3, 4, "You have invited " .. target:Nick() .. " to join " .. gang)
  1779.                     GangNotify(target, 4, 4, "You have been invited to join " .. gang)
  1780.                 else
  1781.                     if msg then
  1782.                         GangNotify(ply, 3, 4, "Invite failed. " .. msg)
  1783.                     else
  1784.                         GangNotify(ply, 3, 4, "Invite failed.")
  1785.                     end
  1786.                 end
  1787.             end)
  1788.         end)
  1789.     end)
  1790.  
  1791.     return ""
  1792. end
  1793.  
  1794. AddChatCommand("/gang_invite", GC_Invite)
  1795.  
  1796. -- /kick <player>
  1797. local function GC_Kick(ply, cmd, args)
  1798.     -- find our gang name
  1799.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1800.         if not gang then return end
  1801.         -- find our target
  1802.         local target = args[1]
  1803.         if target == "" then return end
  1804.         local reason = args[2] or ""
  1805.  
  1806.         if target == ply:SteamID() then
  1807.             GangNotify(ply, 3, 4, "You can't kick yourself")
  1808.  
  1809.             return ""
  1810.         end
  1811.  
  1812.         -- check they're in our gang
  1813.         GangWars.DB.GetPlayerGang(target, function(tgang)
  1814.             if not tgang or tgang ~= gang then return "" end
  1815.  
  1816.             -- find our rank
  1817.             GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1818.                 if not my_rank then return end
  1819.  
  1820.                 -- check other guys rank
  1821.                 --  AND `rank` < 6
  1822.                 isql:QueryValue("SELECT `rank` FROM gw_gang_members WHERE `steam` = " .. isql:Escape(target) .. ";", function(other_rank)
  1823.                     if not other_rank then return end
  1824.                     local rank_ok = false
  1825.  
  1826.                     -- rank setting permissions. leaders can always kick
  1827.                     if my_rank <= 1 then
  1828.                         rank_ok = true
  1829.                         -- vice leaders can kick captains
  1830.                     elseif my_rank == 2 and other_rank > 2 then
  1831.                         rank_ok = true
  1832.                     elseif my_rank == 3 and other_rank > 3 then
  1833.                         -- captains can kick vices
  1834.                         rank_ok = true
  1835.                     end
  1836.  
  1837.                     -- check the target isn't higher ranking than us if we're not leader
  1838.                     if my_rank > 1 and other_rank <= my_rank then
  1839.                         rank_ok = false
  1840.                     end
  1841.  
  1842.                     -- invites can only be kicked by leaders and vice
  1843.                     if other_rank >= 6 and my_rank > 2 then
  1844.                         rank_ok = false
  1845.                     end
  1846.  
  1847.                     if not rank_ok then
  1848.                         GangNotify(ply, 3, 4, "You don't have the rank to do that")
  1849.  
  1850.                         return
  1851.                     end
  1852.  
  1853.                     -- remove them
  1854.                     GangWars.DB.RemoveFromGangBySteam(target, gang, function()
  1855.                         net.Start("sv_refresh_topgangs")
  1856.                         net.Broadcast()
  1857.                         InitPlayerGang(ply)
  1858.                         GangNotify(ply, 3, 4, "You have kicked " .. target .. " from the gang")
  1859.                         GangWars.GangLog(gang, ply:Nick() .. " kicked " .. target .. " (" .. reason .. ")", "Kick", ply)
  1860.                         local tply = FindPlayer(target)
  1861.  
  1862.                         if tply then
  1863.                             InitPlayerGang(tply)
  1864.                             GangNotify(tply, 4, 4, "You have been kicked from the " .. gang .. " gang")
  1865.                         end
  1866.                     end)
  1867.                 end)
  1868.             end)
  1869.         end, true)
  1870.     end)
  1871.  
  1872.     return ""
  1873. end
  1874.  
  1875. --AddChatCommand("/gang_kick", GC_Kick)
  1876. concommand.Add("gang_kick", GC_Kick)
  1877.  
  1878. -- /promote <rank> <player>
  1879. local function GC_Promote(ply, cmd, args)
  1880.     -- find our gang name
  1881.     GangWars.DB.GetPlayerGang(ply, function(gang)
  1882.         if not gang then return "" end
  1883.         --local words = string.Explode(" ", args)
  1884.         --if #words ~= 2 then return "" end
  1885.         local ptype = args[1]
  1886.         -- find our target
  1887.         local target = args[2]
  1888.  
  1889.         if target == ply:SteamID() then
  1890.             GangNotify(ply, 3, 4, "You can't change your own rank")
  1891.  
  1892.             return ""
  1893.         end
  1894.  
  1895.         -- check they're in our gang
  1896.         GangWars.DB.GetPlayerGang(target, function(tgang)
  1897.             if not tgang or tgang ~= gang then return "" end
  1898.  
  1899.             -- check our rank
  1900.             GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1901.                 if not my_rank then return "" end
  1902.  
  1903.                 -- check other guys rank
  1904.                 GangWars.DB.GetPlayerGangRank(target, function(other_rank)
  1905.                     if not other_rank then return "" end
  1906.                     local target_rank = tonumber(ptype)
  1907.                     local rank_ok = false
  1908.  
  1909.                     -- rank setting permissions. leaders can set all ranks
  1910.                     if my_rank <= 1 then
  1911.                         rank_ok = true
  1912.                         -- vice leaders can set up to captain
  1913.                     elseif my_rank == 2 and target_rank > 2 then
  1914.                         rank_ok = true
  1915.                     elseif my_rank == 3 and target_rank > 3 then
  1916.                         -- captains can set vices
  1917.                         rank_ok = true
  1918.                     end
  1919.  
  1920.                     -- check the target isn't higher ranking than us if we're not leader
  1921.                     if my_rank > 1 and other_rank <= my_rank then
  1922.                         rank_ok = false
  1923.                     end
  1924.  
  1925.                     -- abandon setting the same rank
  1926.                     if target_rank == other_rank then
  1927.                         rank_ok = false
  1928.                     end
  1929.  
  1930.                     if not rank_ok then
  1931.                         GangNotify(ply, 3, 4, "You don't have the rank to do that")
  1932.  
  1933.                         return ""
  1934.                     end
  1935.  
  1936.                     -- is it a promotion or demotion?
  1937.                     local promotion = target_rank < other_rank
  1938.  
  1939.                     -- set targets rank
  1940.                     GangWars.DB.SetPlayerGangRank(target, gang, target_rank, function(q)
  1941.                         if q then
  1942.                             local text = "promoted"
  1943.  
  1944.                             if not promotion then
  1945.                                 text = "demoted"
  1946.                             end
  1947.  
  1948.                             InitPlayerGang(ply)
  1949.                             local target = FindPlayer(args[2])
  1950.  
  1951.                             if IsValid(target) then
  1952.                                 InitPlayerGang(target)
  1953.                                 GangNotify(target, 4, 4, "You have been " .. text .. " within the gang")
  1954.                                 GangNotify(ply, 3, 4, "You " .. text .. " " .. target:Nick())
  1955.                                 GangWars.GangLog(gang, ply:Nick() .. " " .. text .. " " .. target:Nick(), "Promote", ply)
  1956.                             else
  1957.                                 GangNotify(ply, 3, 4, "You " .. text .. " " .. args[2])
  1958.                                 GangWars.GangLog(gang, ply:Nick() .. " " .. text .. " " .. args[2], "Promote", ply)
  1959.                             end
  1960.                         end
  1961.                     end)
  1962.                 end)
  1963.             end)
  1964.         end)
  1965.     end)
  1966.  
  1967.     return ""
  1968. end
  1969.  
  1970. --AddChatCommand("/gang_promote", GC_Promote)
  1971. concommand.Add("gang_promote", GC_Promote)
  1972.  
  1973. -- /add rival
  1974. local function GC_AddRival(ply, args)
  1975.     -- find our gang name
  1976.     GangWars.DB.GetPlayerGangInfo(ply, function(gang)
  1977.         if not gang then return "" end
  1978.  
  1979.         -- check we're not naming ourself
  1980.         if gang.name == args then
  1981.             GangNotify(ply, 3, 4, "You can't name your own gang as a rival")
  1982.  
  1983.             return
  1984.         end
  1985.  
  1986.         if tonumber(gang.points) <= 0 then
  1987.             GangNotify(ply, 3, 4, args .. " can't be rivalled because your gang has no gang points")
  1988.  
  1989.             return
  1990.         end
  1991.  
  1992.         -- check rank
  1993.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  1994.             if not my_rank or tonumber(my_rank) > 2 then
  1995.                 GangNotify(ply, 3, 4, "Only leaders and vice leaders can add rivals")
  1996.  
  1997.                 return
  1998.             end
  1999.  
  2000.             -- check the other gang exists
  2001.             isql:QueryRow("SELECT `level`, `points` FROM `gw_gangs` WHERE `name` = " .. isql:Escape(args) .. ";", function(q)
  2002.                 if not q or tonumber(q.level) < (ply:GetNW2Int("gang_level") - 5) then
  2003.                     GangNotify(ply, 3, 4, args .. " are too low level to be your rival")
  2004.  
  2005.                     return
  2006.                 end
  2007.  
  2008.                 if tonumber(q.points) <= 0 then
  2009.                     GangNotify(ply, 3, 4, args .. " can't be rivalled because they have no gang points")
  2010.  
  2011.                     return
  2012.                 end
  2013.  
  2014.                 -- check they aren't already our rival
  2015.                 isql:QueryValue("SELECT COUNT(*) FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(gang.name) .. " AND `rival` = " .. isql:Escape(args) .. ";", function(q)
  2016.                     if q and tonumber(q) > 0 then
  2017.                         GangNotify(ply, 3, 4, "You are already rivals with that gang")
  2018.  
  2019.                         return
  2020.                     end
  2021.  
  2022.                     -- and the other way around
  2023.                     isql:QueryValue("SELECT COUNT(*) FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang.name) .. ";", function(q)
  2024.                         if q and tonumber(q) > 0 then
  2025.                             GangNotify(ply, 3, 4, "You are already rivals with that gang")
  2026.  
  2027.                             return
  2028.                         end
  2029.  
  2030.                         -- check the rivalry is allowed
  2031.                         isql:QueryValue("SELECT DATEDIFF(`expires`, NOW()) AS diff FROM `gw_gang_norival` WHERE `gang` = " .. isql:Escape(gang.name) .. " AND `rival` = " .. isql:Escape(args) .. " AND DATEDIFF(`expires`, NOW()) > 0;", function(rcount)
  2032.                             if rcount and tonumber(rcount) > 0 then
  2033.                                 GangNotify(ply, 3, 4, "You are not allowed to rival that gang for " .. rcount .. " more days")
  2034.  
  2035.                                 return
  2036.                             end
  2037.  
  2038.                             -- delete any norival entry for this gang
  2039.                             isql:Query("DELETE FROM `gw_gang_norival` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang.name) .. ";", function()
  2040.                                 -- add rival relationship
  2041.                                 isql:Query("INSERT INTO `gw_gang_rivals` (`gang`, `rival`, `started`) VALUES(" .. isql:Escape(gang.name) .. ", " .. isql:Escape(args) .. ", NOW());", function()
  2042.                                     isql:Query("INSERT INTO `gw_gang_rivals` (`gang`, `rival`, `started`) VALUES(" .. isql:Escape(args) .. ", " .. isql:Escape(gang.name) .. ", NOW());", function()
  2043.                                         -- add them
  2044.                                         --InitPlayerGang(ply)
  2045.                                         --GangNotify(ply, 3, 4, "You have named " .. args .. " as a rival gang")
  2046.                                         NotifyGang(gang.name, 4, 4, "A gang rivalry has been started against " .. args .. "!")
  2047.                                         NotifyGang(args, 4, 4, gang.name .. " have declared a gang rivalry has against you!")
  2048.  
  2049.                                         for k, v in pairs(player.GetAll()) do
  2050.                                             if IsValid(v) then
  2051.                                                 if v:Gang() == gang.name or v:Gang() == args then
  2052.                                                     InitPlayerGang(v)
  2053.                                                 end
  2054.                                             end
  2055.                                         end
  2056.                                     end)
  2057.                                 end)
  2058.                             end)
  2059.                         end)
  2060.                     end)
  2061.                 end)
  2062.             end)
  2063.         end)
  2064.     end)
  2065.  
  2066.     return ""
  2067. end
  2068.  
  2069. AddChatCommand("/gang_addrival", GC_AddRival)
  2070. -- request mercy
  2071. local BlockMercySpam = {}
  2072.  
  2073. local function GC_ReqMercy(ply, args)
  2074.     if not IsValid(ply) then return end
  2075.     if BlockMercySpam[ply:SteamID()] and BlockMercySpam[ply:SteamID()] > CurTime() then return end
  2076.     BlockMercySpam[ply:SteamID()] = CurTime() + 5
  2077.  
  2078.     -- find our gang name
  2079.     GangWars.DB.GetPlayerGang(ply, function(gang)
  2080.         if not gang then return "" end
  2081.  
  2082.         -- find our rank
  2083.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  2084.             if not my_rank or tonumber(my_rank) > 2 then
  2085.                 GangNotify(ply, 3, 4, "Only leaders and co-leaders can request mercy")
  2086.  
  2087.                 return
  2088.             end
  2089.  
  2090.             -- try and make them win
  2091.             GangWars.DB.RivalryWin(args, gang)
  2092.         end)
  2093.     end)
  2094.  
  2095.     return ""
  2096. end
  2097.  
  2098. AddChatCommand("/gang_mercy", GC_ReqMercy)
  2099.  
  2100. -- request truce
  2101. local function GC_ReqTruce(ply, args)
  2102.     -- find our gang name
  2103.     GangWars.DB.GetPlayerGang(ply, function(gang)
  2104.         if not gang then return "" end
  2105.  
  2106.         -- find our rank
  2107.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  2108.             if not my_rank or tonumber(my_rank) > 2 then
  2109.                 GangNotify(ply, 3, 4, "Only leaders and co-leaders can request a truce")
  2110.  
  2111.                 return
  2112.             end
  2113.  
  2114.             -- see if other gang is requesting a truce
  2115.             isql:QueryValue("SELECT `truce` FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang) .. ";", function(truce)
  2116.                 if not truce then
  2117.                     GangNotify(ply, 3, 4, "You don't seem to have a rivalry with " .. args)
  2118.  
  2119.                     return
  2120.                 end
  2121.  
  2122.                 if tonumber(truce) == 1 then
  2123.                     -- truce is agreed. remove the rivalry
  2124.                     isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(gang) .. " AND `rival` = " .. isql:Escape(args) .. ";", function()
  2125.                         isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang) .. ";", function()
  2126.                             -- refresh their view
  2127.                             InitPlayerGang(ply)
  2128.                             NotifyGang(gang, 4, 4, "A truce with " .. args .. " has been agreed!")
  2129.                             NotifyGang(args, 4, 4, "A truce with " .. gang .. " has been agreed!")
  2130.                         end)
  2131.                     end)
  2132.                 else
  2133.                     -- set truce request
  2134.                     isql:Query("UPDATE `gw_gang_rivals` SET `truce` = '1' WHERE `gang` = " .. isql:Escape(gang) .. " AND `rival` = " .. isql:Escape(args) .. ";", function()
  2135.                         -- refresh their view
  2136.                         InitPlayerGang(ply)
  2137.                         --GangNotify(ply, 3, 4, "You have requested a truce with " .. args)
  2138.                         NotifyGang(gang, 4, 4, "You have requested a truce with " .. args)
  2139.                         NotifyGang(args, 4, 4, gang .. " have requested a truce!")
  2140.                     end)
  2141.                 end
  2142.             end)
  2143.         end)
  2144.     end)
  2145.  
  2146.     return ""
  2147. end
  2148.  
  2149. AddChatCommand("/gang_truce", GC_ReqTruce)
  2150.  
  2151. -- cancel truce
  2152. local function GC_CancelTruce(ply, args)
  2153.     -- find our gang name
  2154.     GangWars.DB.GetPlayerGang(ply, function(gang)
  2155.         if not gang then return "" end
  2156.  
  2157.         -- find our rank
  2158.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  2159.             if not my_rank or tonumber(my_rank) > 2 then
  2160.                 GangNotify(ply, 3, 4, "Only leaders and co-leaders can cancel a truce")
  2161.  
  2162.                 return
  2163.             end
  2164.  
  2165.             -- just check they exist
  2166.             isql:Query("SELECT `truce` FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(args) .. " AND `rival` = " .. isql:Escape(gang) .. ";", function(truce)
  2167.                 if truce then
  2168.                     -- set truce request
  2169.                     isql:Query("UPDATE `gw_gang_rivals` SET `truce` = '0' WHERE `gang` = " .. isql:Escape(gang) .. " AND `rival` = " .. isql:Escape(args) .. ";", function()
  2170.                         -- refresh their view
  2171.                         InitPlayerGang(ply)
  2172.                         GangNotify(ply, 3, 4, "You have cancelled the truce request with " .. args)
  2173.                     end)
  2174.                 end
  2175.             end)
  2176.         end)
  2177.     end)
  2178.  
  2179.     return ""
  2180. end
  2181.  
  2182. AddChatCommand("/gang_canceltruce", GC_CancelTruce)
  2183.  
  2184. -- /accept
  2185. local function GC_AcceptInvite(ply, args)
  2186.     GangWars.DB.AcceptInvite(ply, args, function(q)
  2187.         if q then
  2188.             InitPlayerGang(ply, function()
  2189.                 ply:GangStorageRefresh()
  2190.                 ply:GangLogRefresh()
  2191.                 GangNotify(ply, 3, 4, "You accepted the gang invite from " .. args)
  2192.                 GangWars.GangLog(args, ply:Nick() .. " joined the gang", "Join", ply)
  2193.             end)
  2194.         end
  2195.     end)
  2196.  
  2197.     return ""
  2198. end
  2199.  
  2200. AddChatCommand("/gang_accept", GC_AcceptInvite)
  2201.  
  2202. -- /reject
  2203. local function GC_RejectInvite(ply, args)
  2204.     GangWars.DB.RejectInvite(ply, args, function(q)
  2205.         if q then
  2206.             InitPlayerGang(ply)
  2207.             GangNotify(ply, 3, 4, "You rejected the gang invite from " .. args)
  2208.             GangWars.GangLog(args, ply:Nick() .. " rejected our gang invite", "Reject", ply)
  2209.         end
  2210.     end)
  2211.  
  2212.     return ""
  2213. end
  2214.  
  2215. AddChatCommand("/gang_reject", GC_RejectInvite)
  2216.  
  2217. -- set item purchase permission
  2218. local function GC_SetBuyPermission(ply, cmd, args)
  2219.     --Msg("GC_SetBuyPermission\n")
  2220.     -- find our gang name
  2221.     GangWars.DB.GetPlayerGang(ply, function(gang)
  2222.         if not gang then return "" end
  2223.  
  2224.         --Msg("GetPlayerGang\n")
  2225.         -- find our rank
  2226.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  2227.             --Msg("GetPlayerGangRank check\n")
  2228.             if not my_rank or tonumber(my_rank) > 2 then return end
  2229.             --Msg("GetPlayerGangRank ok\n")
  2230.             local itemid = args[1]
  2231.             local perms = args[2]
  2232.  
  2233.             -- delete any existing permissions
  2234.             isql:Query("DELETE FROM`gw_gang_permissions` WHERE `gang` = " .. isql:Escape(gang) .. " AND `item` = " .. isql:Escape(itemid) .. ";", function()
  2235.                 --Msg("DELETE FROM`gw_gang_permissions`\n")
  2236.                 -- insert new permissions
  2237.                 isql:Query("INSERT INTO `gw_gang_permissions` (`gang`, `item`, `permission`) VALUES(" .. isql:Escape(gang) .. ", " .. isql:Escape(itemid) .. ", " .. isql:Escape(perms) .. ");", function() end) --Msg("done!\n")
  2238.             end)
  2239.         end)
  2240.     end)
  2241. end
  2242.  
  2243. concommand.Add("gang_permission", GC_SetBuyPermission)
  2244.  
  2245. -- gang buy
  2246. local function GC_BuyItem(ply, args)
  2247.     -- Can't buy gang stuff as a cop
  2248.     if ply:GetProfession().police then
  2249.         Notify(ply, 4, 4, "You cant buy gang stuff when working as AnkhTek Security!")
  2250.  
  2251.         return ""
  2252.     end
  2253.  
  2254.     -- find our gang name
  2255.     GangWars.DB.GetPlayerGang(ply, function(gang)
  2256.         if not gang then
  2257.             Msg("Warning: /gang_buy player had no gang?\n")
  2258.  
  2259.             return
  2260.         end
  2261.  
  2262.         -- find our rank
  2263.         GangWars.DB.GetPlayerGangRank(ply, function(my_rank)
  2264.             if not my_rank then
  2265.                 Msg("Warning: /gang_buy player had no rank?\n")
  2266.  
  2267.                 return
  2268.             end
  2269.  
  2270.             -- find permissions for the item
  2271.             isql:QueryValue("SELECT `permission` FROM `gw_gang_permissions` WHERE `gang` = " .. isql:Escape(gang) .. " AND `item` = " .. isql:Escape(args) .. ";", function(perm)
  2272.                 if not perm then
  2273.                     --Msg("Warning: /gang_buy " .. args .. ": couldn't find a permission entry for this item\n")
  2274.                     --return
  2275.                     -- no permissions = default. nobody  can buy.
  2276.                     perm = 0
  2277.                 end
  2278.  
  2279.                 -- check our rank has permission to buy
  2280.                 local function HasItemPerm(perms, rank)
  2281.                     local d = 16
  2282.                     local pms = {0, 0, 0, 0, 0}
  2283.                     local r = 5
  2284.  
  2285.                     while perms > 0 do
  2286.                         if perms - d >= 0 then
  2287.                             perms = perms - d
  2288.                             pms[r] = 1
  2289.                         end
  2290.  
  2291.                         d = d / 2
  2292.                         r = r - 1
  2293.                     end
  2294.  
  2295.                     return pms[rank] == 1
  2296.                 end
  2297.  
  2298.                 -- check our rank has permission to buy
  2299.                 if not HasItemPerm(perm, my_rank) then
  2300.                     GangNotify(ply, 3, 4, "You don't have permission to buy that!")
  2301.  
  2302.                     return
  2303.                 end
  2304.  
  2305.                 -- find gang info
  2306.                 GangWars.DB.GetGangInfo(gang, function(info)
  2307.                     if not info then
  2308.                         Msg("GC_BuyItem: GangWars.DB.GetGangInfo returned nil")
  2309.  
  2310.                         return
  2311.                     end
  2312.  
  2313.                     local gangmoney = tonumber(info.money)
  2314.                     local ganglevel = tonumber(info.level)
  2315.                     local found = false
  2316.  
  2317.                     -- find item in gang shop
  2318.                     for k, v in pairs(Gang.GangShop) do
  2319.                         if v.id == args then
  2320.                             found = v
  2321.                             break
  2322.                         end
  2323.                     end
  2324.  
  2325.                     -- abandon if item not found
  2326.                     if not found then
  2327.                         GangNotify(ply, 3, 4, "Item not found in gang shop")
  2328.  
  2329.                         return
  2330.                     end
  2331.  
  2332.                     -- abandon if we're not high enough level
  2333.                     if found.level > ganglevel then
  2334.                         GangNotify(ply, 3, 4, "Your gang must be level " .. found.level .. " to spawn that!")
  2335.  
  2336.                         return
  2337.                     end
  2338.  
  2339.                     -- fix the price
  2340.                     local item_price = found.price
  2341.  
  2342.                     -- discount upgrade
  2343.                     if ply.GangInfo and found.entity ~= "gang_stash" then
  2344.                         if ply.GangInfo.shopboost and ply.GangInfo.shopboost > 0 then
  2345.                             local txt, aff = Gang.GetUpgradeEffect("shopboost", ply.GangInfo.shopboost - 1)
  2346.                             item_price = item_price - math.floor((item_price / 100) * aff)
  2347.                         end
  2348.                     end
  2349.  
  2350.                     -- abandon if we can't afford it
  2351.                     if gangmoney < item_price then
  2352.                         GangNotify(ply, 1, 4, "Your gang can not afford this!")
  2353.  
  2354.                         return
  2355.                     end
  2356.  
  2357.                     -- abandon if gang is past its stash limit
  2358.                     if found.entity == "gang_stash" then
  2359.                         local stashes = {}
  2360.  
  2361.                         for k, v in pairs(ents.FindByClass(found.entity)) do
  2362.                             if v.gang == gang then
  2363.                                 table.insert(stashes, v)
  2364.                             end
  2365.                         end
  2366.  
  2367.                         if #stashes >= math.min(ganglevel, 4) then
  2368.                             GangNotify(ply, 1, 4, "You already have the max of " .. math.min(ganglevel, 4) .. " stashes")
  2369.  
  2370.                             return
  2371.                         end
  2372.                     end
  2373.  
  2374.                     -- abandon if gang is past its generator limit
  2375.                     if found.entity == "base_generator" then
  2376.                         local stashes = {}
  2377.  
  2378.                         for k, v in pairs(ents.FindByClass(found.entity)) do
  2379.                             if v.gang == gang then
  2380.                                 table.insert(stashes, v)
  2381.                             end
  2382.                         end
  2383.  
  2384.                         if #stashes >= 2 then
  2385.                             GangNotify(ply, 1, 4, "Your gang already have the max of 2 generators")
  2386.  
  2387.                             return
  2388.                         end
  2389.                     end
  2390.  
  2391.                     -- abandon if gang is past its printer limit
  2392.                     if found.entity == "gang_printer" then
  2393.                         local stashes = {}
  2394.  
  2395.                         for k, v in pairs(ents.FindByClass(found.entity)) do
  2396.                             if v.gang == gang then
  2397.                                 table.insert(stashes, v)
  2398.                             end
  2399.                         end
  2400.  
  2401.                         --MsgN("checking gang printers. search is for '" .. found.entity .."', initial count is " .. #ents.FindByClass(found.entity)  .. ", actual is " .. #stashes)
  2402.                         if #stashes >= 4 then
  2403.                             GangNotify(ply, 1, 4, "You already have the max of 4 gang printers")
  2404.  
  2405.                             return
  2406.                         end
  2407.                     end
  2408.  
  2409.                     -- abandon if gang is past its printer limit
  2410.                     if found.entity == "orb_forge" then
  2411.                         local stashes = {}
  2412.  
  2413.                         for k, v in pairs(ents.FindByClass(found.entity)) do
  2414.                             if v.gang == gang then
  2415.                                 table.insert(stashes, v)
  2416.                             end
  2417.                         end
  2418.  
  2419.                         if #stashes >= 1 then
  2420.                             GangNotify(ply, 1, 4, "You already have the max of 1 gang orb forge!")
  2421.  
  2422.                             return
  2423.                         end
  2424.                     end
  2425.  
  2426.                     -- abandon if gang is past its overclocker limit
  2427.                     if found.entity == "overclocker_forge" then
  2428.                         local stashes = {}
  2429.  
  2430.                         for k, v in pairs(ents.FindByClass(found.entity)) do
  2431.                             if v.gang == gang then
  2432.                                 table.insert(stashes, v)
  2433.                             end
  2434.                         end
  2435.  
  2436.                         if #stashes >= 4 then
  2437.                             GangNotify(ply, 1, 4, "You already have the max of 4 overclocker forges!")
  2438.  
  2439.                             return
  2440.                         end
  2441.                     end
  2442.  
  2443.                     -- charge gang
  2444.                     GangWars.DB.AddGangMoney(gang, -item_price, function()
  2445.                         GangNotify(ply, 1, 4, "You have bought a " .. found.name .. " for " .. CUR .. GangWars.FormatMoney(item_price))
  2446.                         GangWars.GangLogNumber(gang, item_price, "Buy", ply, found.name)
  2447.                         local trace = {}
  2448.                         trace.start = ply:EyePos()
  2449.                         trace.endpos = trace.start + ply:GetAimVector() * 85
  2450.                         trace.filter = ply
  2451.                         local tr = util.TraceLine(trace)
  2452.                         -- create the item
  2453.                         local spawnitem
  2454.                         spawnitem = ents.Create(found.entity)
  2455.                         spawnitem.SID = ply.SID
  2456.                         spawnitem.gang = gang
  2457.                         spawnitem:SetNWEntity("owning_ent", ply)
  2458.                         spawnitem:SetNW2String("Owner", "Shared")
  2459.                         spawnitem:SetNW2String("gang", gang)
  2460.                         spawnitem.Owner = ply
  2461.                         spawnitem.OwnerID = ply:SteamID()
  2462.                         spawnitem:SetNW2Int("original_cost", item_price)
  2463.                         spawnitem:SetPos(tr.HitPos)
  2464.                         spawnitem.onlyremover = true
  2465.                         spawnitem.nodupe = true
  2466.  
  2467.                         if found.model then
  2468.                             spawnitem.weaponclass = found.subclass
  2469.                             spawnitem:SetModel(found.model)
  2470.                         end
  2471.  
  2472.                         -- create CII data
  2473.                         local ciidata = {}
  2474.                         ciidata.class = "item"
  2475.                         ciidata.subclass = found.subclass
  2476.                         ciidata.ent = found.entity
  2477.                         ciidata.name = found.name or ""
  2478.                         ciidata.model = found.model or ""
  2479.                         ciidata.icon = found.icon
  2480.                         ciidata.value = item_price or 0
  2481.                         ciidata.level_lock = found.level or 0
  2482.                         ciidata.quantity = 0
  2483.                         ciidata.level = 1
  2484.                         ciidata.entityex = found.subclass
  2485.  
  2486.                         -- See if the item supports the CII interface
  2487.                         if spawnitem.CIILoad then
  2488.                             spawnitem:CIILoad(ciidata)
  2489.                         end
  2490.  
  2491.                         -- See if the item supports the newer LoadItem interface (it must have a ref)
  2492.                         if spawnitem.LoadItem then
  2493.                             local ref = GangWars.Item.FindByName(found.name)
  2494.                             spawnitem:LoadItem(ref)
  2495.                         end
  2496.  
  2497.                         -- Else try the subclass interface
  2498.                         if spawnitem.SetSubclass then
  2499.                             spawnitem:SetSubclass(found.subclass)
  2500.                         end
  2501.  
  2502.                         spawnitem:Spawn()
  2503.  
  2504.                         -- do it twice for the benefit of gang coolers etc (badly coded ents)
  2505.                         if spawnitem.SetSubclass then
  2506.                             spawnitem:SetSubclass(found.subclass)
  2507.                         end
  2508.                         spawnitem:CPPISetOwner(ply)
  2509.                     end)
  2510.                 end)
  2511.             end)
  2512.         end)
  2513.     end)
  2514.  
  2515.     return ""
  2516. end
  2517.  
  2518. AddChatCommand("/gang_buy", GC_BuyItem)
  2519.  
  2520. --////////////////////////////////////////////////////////////////////////////
  2521. -- Util
  2522. function Gang.SendRivalList(rp, my_gang)
  2523.     if not my_gang then return end
  2524.  
  2525.     -- send full member list
  2526.     GangWars.DB.GetGangRivalList(my_gang, function(members)
  2527.         if not members then return end
  2528.  
  2529.         for k, v in pairs(members) do
  2530.             local col = string.Explode(" ", v.color)
  2531.  
  2532.             if #col == 3 then
  2533.                 v.color = Color(tonumber(col[1]), tonumber(col[2]), tonumber(col[3]), 255)
  2534.             end
  2535.  
  2536.             local col = string.Explode(" ", v.color2)
  2537.  
  2538.             if #col == 3 then
  2539.                 v.color2 = Color(tonumber(col[1]), tonumber(col[2]), tonumber(col[3]), 255)
  2540.             end
  2541.         end
  2542.  
  2543.         -- store the list - we use this to decide wether to drop evidence in sv_gamemode_functions.lua
  2544.         local tmp = {}
  2545.  
  2546.         for k, v in pairs(members) do
  2547.             table.insert(tmp, v.name)
  2548.         end
  2549.  
  2550.         rp.GangRivals = tmp
  2551.         net.Start("ds_gang_rivals")
  2552.         net.WriteTable(members)
  2553.         net.Send(rp)
  2554.     end)
  2555. end
  2556.  
  2557. function Gang.SendMemberList(rp, my_gang)
  2558.     if not my_gang then return end
  2559.  
  2560.     -- send full member list
  2561.     --[[
  2562.     GangWars.DB.GetPlayerGangMemberList(my_gang,
  2563.     function(members)
  2564.         if not members then return end
  2565.         net.Start("ds_gang_members")
  2566.         net.WriteTable(members)
  2567.         net.Send(rp)
  2568.     end)
  2569.     ]]
  2570.     GangWars.DB.GetGangMemberStats(my_gang, rp:SteamID(), function(members)
  2571.         if not members then return end
  2572.         net.Start("ds_gang_members")
  2573.         net.WriteTable(members)
  2574.         net.Send(rp)
  2575.     end)
  2576. end
  2577.  
  2578. function Gang.SendInfo(rp, my_gang)
  2579.     if not my_gang then return end
  2580.  
  2581.     -- set gang info
  2582.     GangWars.DB.GetGangInfo(my_gang, function(info)
  2583.         -- get members for count
  2584.         GangWars.DB.GetPlayerGangMemberList(my_gang, function(members)
  2585.             -- get shop permissions
  2586.             isql:Query("SELECT * FROM `gw_gang_permissions` WHERE `gang` = " .. isql:Escape(my_gang) .. ";", function(perms)
  2587.                 local shop_permissions = {}
  2588.  
  2589.                 if perms then
  2590.                     for k, v in ipairs(perms) do
  2591.                         shop_permissions[tostring(v.item)] = v.permission
  2592.                     end
  2593.                 end
  2594. --[[
  2595.                 local col = string.Explode(" ", info.color)
  2596.  
  2597.                 if #col == 3 then
  2598.                     col = Color(tonumber(col[1]), tonumber(col[2]), tonumber(col[3]), 255)
  2599.                 end
  2600.  
  2601.                 local col2 = string.Explode(" ", info.color2)
  2602.  
  2603.                 if #col2 == 3 then
  2604.                     col2 = Color(tonumber(col2[1]), tonumber(col2[2]), tonumber(col2[3]), 255)
  2605.                 end
  2606. ]]
  2607.                 -- this is pretty pointless, but could save copying over unwanted data (eg password)
  2608.                 local MyGang = {}
  2609.                 MyGang.name = info['name']
  2610.                 MyGang.logo = info['logo']
  2611.                 MyGang.message = info['message']
  2612.                 MyGang.points = tonumber(info['points'])
  2613.                 MyGang.color = Color(0, 0, 0)
  2614.                 MyGang.color2 = Color(255, 0, 0)
  2615.                 MyGang.xp = tonumber(info['xp'])
  2616.                 MyGang.level = tonumber(info['level'])
  2617.                 MyGang.money = tonumber(info['money'])
  2618.                 MyGang.hpboost = tonumber(info['hpboost'])
  2619.                 MyGang.regen = tonumber(info['regen'])
  2620.                 MyGang.extraitems = tonumber(info['extraitems'])
  2621.                 MyGang.xpboost = tonumber(info['xpboost'])
  2622.                 MyGang.speedboost = tonumber(info['speedboost'])
  2623.                 MyGang.printboost = tonumber(info['printboost'])
  2624.                 MyGang.drugboost = tonumber(info['drugboost'])
  2625.                 MyGang.dropboost = tonumber(info['dropboost'])
  2626.                 -- gang patch
  2627.                 MyGang.armorboost = tonumber(info['armorboost'])
  2628.                 --MyGang.memberboost = tonumber(info['memberboost'])
  2629.                 --MyGang.rivalboost = tonumber(info['rivalboost'])
  2630.                 MyGang.shopboost = tonumber(info['shopboost'])
  2631.                 --MyGang.ghostboost = tonumber(info['ghostboost'])
  2632.                 MyGang.ppocketboost = tonumber(info['ppocketboost'])
  2633.                 MyGang.bankboost = tonumber(info['bankboost'])
  2634.                 MyGang.missionboost = tonumber(info['missionboost'])
  2635.                 MyGang.gangxpboost = tonumber(info['gangxpboost'])
  2636.                 --MyGang.capboost = tonumber(info['capboost'])
  2637.                 MyGang.shop_permissions = shop_permissions
  2638.                 MyGang.members = table.Count(members)
  2639.                 net.Start("ds_gang_info")
  2640.                 net.WriteTable(MyGang)
  2641.                 net.Send(rp)
  2642.             end)
  2643.         end)
  2644.     end)
  2645. end
  2646.  
  2647. --[[
  2648. // Refreshes a gangs info for all online players in the gang
  2649. function UpdateClientGangInfo(gang_name)
  2650.     local RP = RecipientFilter()
  2651.  
  2652.     // Find all gangmembers
  2653.     GangWars.DB.GetPlayerGangMemberList(gang_name,
  2654.     function(mlist)
  2655.         if not mlist then return false end
  2656.  
  2657.         // Find gangmembers who are on the server
  2658.         for id, row in pairs(mlist) do
  2659.             local p = FindPlayer(row['name'])
  2660.             if p and IsValid(p) and p:IsPlayer() then
  2661.                 RP:AddPlayer(p)
  2662.             end
  2663.         end
  2664.  
  2665.         // Send updates
  2666.         Gang.SendInfo(RP, gang_name)
  2667.     end)
  2668. end
  2669.  
  2670. // Refreshes a gangs player list for all online players in the gang
  2671. function UpdateClientGangMembers(gang_name)
  2672.     local RP = RecipientFilter()
  2673.  
  2674.     // Find all gangmembers
  2675.     GangWars.DB.GetPlayerGangMemberList(gang_name,
  2676.     function(mlist)
  2677.         if not mlist then return false end
  2678.  
  2679.         // Find gangmembers who are on the server
  2680.         for id, row in pairs(mlist) do
  2681.             local p = FindPlayer(row['name'])
  2682.             if p and IsValid(p) and p:IsPlayer() then
  2683.                 RP:AddPlayer(p)
  2684.             end
  2685.         end
  2686.  
  2687.         // Send updates
  2688.         Gang.SendMemberList(RP, gang_name)
  2689.     end)
  2690. end
  2691. ]]
  2692. -- Updates a single players gang info
  2693. function InitPlayerGang(ply, func)
  2694.     if not ply or not IsValid(ply) then return false end
  2695.     local steamID = ply:SteamID()
  2696.  
  2697.     -- find gang status
  2698.     isql:QueryRow("SELECT `gang`, `rank` FROM `gw_gang_members` WHERE `steam` = " .. isql:Escape(steamID) .. " ORDER BY `rank` ASC;", function(info)
  2699.         if not info or not info.gang or not info.rank then
  2700.             -- set no gang
  2701.             ply:SetNW2String("gang_name", "")
  2702.             ply:SetNW2Int("gang_rank", 0)
  2703.             ply:SetNW2Int("gang_level", 0)
  2704.             ply:SetNW2String("gang_logo", "")
  2705.             ply:SetNW2String("gang_color", "")
  2706.             ply:SetNW2String("gang_color2", "")
  2707.             ply.GangInfo = nil
  2708.             unet.Start("gang_clear", ply)
  2709.             unet.Send(ply)
  2710.  
  2711.             if func then
  2712.                 func(false)
  2713.             end
  2714.  
  2715.             return
  2716.         elseif tonumber(info.rank) == 6 then
  2717.             -- set invited
  2718.             ply:SetNW2String("gang_name", "")
  2719.             ply:SetNW2Int("gang_rank", 0)
  2720.             ply:SetNW2Int("gang_level", 0)
  2721.             ply:SetNW2String("gang_logo", "")
  2722.             ply:SetNW2String("gang_color", "")
  2723.             ply:SetNW2String("gang_color2", "")
  2724.             ply.GangInfo = nil
  2725.             unet.Start("gang_clear", ply)
  2726.             unet.Send(ply)
  2727.             ply:SetNW2Int("gang_invited", true)
  2728.  
  2729.             isql:Query("SELECT `gang` FROM gw_gang_members WHERE `steam` = " .. isql:Escape(steamID) .. ";", function(members)
  2730.                 if members then
  2731.                     net.Start("ds_gang_invites")
  2732.                     net.WriteTable(members)
  2733.                     net.Send(ply)
  2734.                 end
  2735.             end)
  2736.  
  2737.             if func then
  2738.                 func(false)
  2739.             end
  2740.  
  2741.             return
  2742.         else
  2743.             -- set member
  2744.             GangWars.DB.GetGangInfo(info.gang, function(ginfo)
  2745.                 if ginfo then
  2746.                     -- convert ints
  2747.                     ginfo.level = tonumber(ginfo.level)
  2748.                     ginfo.rank = tonumber(ginfo.rank)
  2749.  
  2750.                     for k, v in pairs(ginfo) do
  2751.                         if tonumber(v) ~= nil then
  2752.                             ginfo[k] = tonumber(v)
  2753.                         end
  2754.                     end
  2755.  
  2756.                     -- set network vars
  2757.                     ply:SetNW2String("gang_name", info.gang)
  2758.                     ply:SetNW2Int("gang_rank", info.rank)
  2759.                     ply:SetNW2Int("gang_level", ginfo.level)
  2760.                     ply:SetNW2String("gang_logo", ginfo.logo)
  2761.                     --ply:SetNW2String("gang_color", ginfo.color)
  2762.                     --ply:SetNW2String("gang_color2", ginfo.color2)
  2763.                     ply:SetNW2String("gang_color", "0 0 0")
  2764.                     ply:SetNW2String("gang_color2", "255 0 0")
  2765.                     -- attach gang info data to player
  2766.                     ply.GangInfo = ginfo
  2767.                     Gang.SendRivalList(ply, info.gang)
  2768.                     Gang.SendMemberList(ply, info.gang)
  2769.                     Gang.SendInfo(ply, info.gang)
  2770.                     ply:GangLogRefresh()
  2771.  
  2772.                     if func then
  2773.                         func(true)
  2774.                     end
  2775.                 else
  2776.                     if func then
  2777.                         func(false)
  2778.                     end
  2779.                 end
  2780.             end)
  2781.         end
  2782.     end)
  2783.  
  2784.     return ""
  2785. end
  2786.  
  2787. local function DoRefresh(ply, args)
  2788.     InitPlayerGang(ply, function()
  2789.         ply:GangStorageRefresh()
  2790.     end)
  2791.  
  2792.     return ""
  2793. end
  2794.  
  2795. AddChatCommand("/gang_refresh", DoRefresh)
  2796.  
  2797. hook.Add("PlayerPickedCharacter", "InitGang", function(ply)
  2798.     InitPlayerGang(ply, function()
  2799.         ply:GangStorageRefresh()
  2800.         ply:GangLogRefresh()
  2801.  
  2802.         --MsgN("SELECT `rival`, `members_killed` FROM gw_gang_rivals WHERE `gang` = " .. isql:Escape(ply:Gang()) .. " AND TIME_TO_SEC(TIMEDIFF(NOW(), started))/60/60 > 72;")
  2803.         isql:Query("SELECT `rival`, `members_killed` FROM gw_gang_rivals WHERE `gang` = " .. isql:Escape(ply:Gang()) .. " AND TIME_TO_SEC(TIMEDIFF(NOW(), started))/60/60 > 72;", function(q)
  2804.             if not q then return end
  2805.  
  2806.             --MsgN("looping")
  2807.             for k, v in pairs(q) do
  2808.                 --MsgN("SELECT `members_killed` FROM gw_gang_rivals WHERE `gang` = " .. isql:Escape(v.rival) .. " AND `rival` = " .. isql:Escape(ply:Gang()) .. " AND TIME_TO_SEC(TIMEDIFF(NOW(), started))/60/60 > 72;")
  2809.                 -- we've found a finished war. check who had more kills
  2810.                 local our_kills = v.members_killed
  2811.                 local our_gang = ply:Gang()
  2812.  
  2813.                 isql:QueryValue("SELECT `members_killed` FROM gw_gang_rivals WHERE `gang` = " .. isql:Escape(v.rival) .. " AND `rival` = " .. isql:Escape(ply:Gang()) .. " AND TIME_TO_SEC(TIMEDIFF(NOW(), started))/60/60 > 72;", function(q2)
  2814.                     --MsgN("result = " .. tostring(q2))
  2815.                     if not q2 then return end
  2816.                     local enemy_kills = q2
  2817.                     local enemy_gang = v.rival
  2818.  
  2819.                     --MsgN("fin")
  2820.                     -- if either team has less than 10 kills?
  2821.                     if our_kills == enemy_kills then
  2822.                         NotifyGang(enemy_gang, 4, 4, "The rivalry with " .. our_gang .. " ended in a draw because you both had " .. our_kills .. " kills")
  2823.                         NotifyGang(our_gang, 4, 4, "The rivalry with " .. enemy_gang .. " ended in a draw because you both had " .. our_kills .. " kills")
  2824.                         isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(our_gang) .. " AND `rival` = " .. isql:Escape(enemy_gang) .. ";")
  2825.                         isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(enemy_gang) .. " AND `rival` = " .. isql:Escape(our_gang) .. ";")
  2826.                     elseif our_kills > enemy_kills then
  2827.                         if our_kills < 30 then
  2828.                             NotifyGang(enemy_gang, 4, 4, "The rivalry with " .. our_gang .. " ended with less than 30 kills. Nobody won!")
  2829.                             NotifyGang(our_gang, 4, 4, "The rivalry with " .. enemy_gang .. " ended with less than 30 kills. Nobody won!")
  2830.                             isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(our_gang) .. " AND `rival` = " .. isql:Escape(enemy_gang) .. ";")
  2831.                             isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(enemy_gang) .. " AND `rival` = " .. isql:Escape(our_gang) .. ";")
  2832.                         else
  2833.                             NotifyGang(enemy_gang, 4, 4, "You lost the rivalry vs " .. our_gang .. " after 3 days, with " .. enemy_kills .. " kills")
  2834.                             NotifyGang(our_gang, 4, 4, "You won the rivalry with " .. enemy_gang .. " after 3 days, with " .. our_kills .. " kills")
  2835.                             GangWars.DB.RivalryWin(our_gang, enemy_gang, true)
  2836.                         end
  2837.                     else
  2838.                         if enemy_kills < 30 then
  2839.                             NotifyGang(enemy_gang, 4, 4, "The rivalry with " .. our_gang .. " ended with less than 30 kills. Nobody won!")
  2840.                             NotifyGang(our_gang, 4, 4, "The rivalry with " .. enemy_gang .. " ended with less than 30 kills. Nobody won!")
  2841.                             isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(our_gang) .. " AND `rival` = " .. isql:Escape(enemy_gang) .. ";")
  2842.                             isql:Query("DELETE FROM `gw_gang_rivals` WHERE `gang` = " .. isql:Escape(enemy_gang) .. " AND `rival` = " .. isql:Escape(our_gang) .. ";")
  2843.                         else
  2844.                             NotifyGang(enemy_gang, 4, 4, "You won the rivalry vs " .. our_gang .. " after 3 days, with " .. enemy_kills .. " kills")
  2845.                             NotifyGang(our_gang, 4, 4, "You lost the rivalry with " .. enemy_gang .. " after 3 days, with " .. our_kills .. " kills")
  2846.                             GangWars.DB.RivalryWin(enemy_gang, our_gang, true)
  2847.                         end
  2848.                     end
  2849.                 end)
  2850.             end
  2851.         end)
  2852.     end)
  2853. end)
  2854.  
  2855. -- gang search
  2856. local function GC_Search(ply, args)
  2857.     if string.len(args) < 2 or string.len(args) > 32 then
  2858.         GangNotify(ply, 3, 4, "Invalid Search")
  2859.  
  2860.         return ""
  2861.     end
  2862.  
  2863.     isql:Query("SELECT `name`, `logo`, `color`, `color2`, `level` FROM gw_gangs WHERE `name` LIKE " .. isql:Escape("%" .. args .. "%") .. " LIMIT 15;", function(q)
  2864.         if q then
  2865.             for k, v in pairs(q) do
  2866.                 local col = string.Explode(" ", v.color)
  2867.  
  2868.                 if #col == 3 then
  2869.                     v.color = Color(tonumber(col[1]), tonumber(col[2]), tonumber(col[3]), 255)
  2870.                 end
  2871.  
  2872.                 local col = string.Explode(" ", v.color2)
  2873.  
  2874.                 if #col == 3 then
  2875.                     v.color2 = Color(tonumber(col[1]), tonumber(col[2]), tonumber(col[3]), 255)
  2876.                 end
  2877.             end
  2878.  
  2879.             net.Start("ds_gang_search")
  2880.             net.WriteTable(q)
  2881.             net.Send(ply)
  2882.         end
  2883.     end)
  2884.  
  2885.     return ""
  2886. end
  2887.  
  2888. AddChatCommand("/gang_search", GC_Search)
  2889. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2890. -- Gang Storage
  2891. local meta = FindMetaTable("Player")
  2892.  
  2893. function meta:GangStorageRefresh()
  2894.     if not self.GangInfo or not self.GangInfo.name or self.GangInfo.name == "" then
  2895.         self:SetDataset("gang_storage", {})
  2896.     else
  2897.         self:SetDatasetQueryKeyed("gang_storage", "slot", "SELECT * FROM `view_gang_storage` WHERE `gang` = " .. isql:Escape(self.GangInfo.name) .. ";")
  2898.     end
  2899. end
  2900.  
  2901. function meta:AllGangStorageRefresh()
  2902.     if not self.GangInfo or not self.GangInfo.name or self.GangInfo.name == "" then return end
  2903.  
  2904.     for k, v in pairs(player.GetAll()) do
  2905.         if v.GangInfo and v.GangInfo.name and v.GangInfo.name == self.GangInfo.name then
  2906.             v:SetDatasetQueryKeyed("gang_storage", "slot", "SELECT * FROM `view_gang_storage` WHERE `gang` = " .. isql:Escape(self.GangInfo.name) .. ";")
  2907.         end
  2908.     end
  2909. end
  2910.  
  2911. --/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2912. function GangWars.DBX.GangStorageAdd(ply, itemid, slotid, func)
  2913.     if not IsValid(ply) or not ply.GangInfo then
  2914.         func(nil)
  2915.  
  2916.         return
  2917.     end
  2918.  
  2919.     local steamID = ply:SteamID()
  2920.  
  2921.     -- stop exploit where you drop an item & drop from storage
  2922.     if ply.DroppingItem or ply.upgrading then
  2923.         GangWars.Log("cheat", ply, "JIMMYS Gang Storage Exploit (GSTADD)") -- log jimmy lol
  2924.         ply:GangStorageRefresh()
  2925.         ply:InvRefresh()
  2926.         -- timer.Simple(1, function()
  2927.         -- ply:InvRefresh()
  2928.         -- end)
  2929.  
  2930.         return
  2931.     end
  2932.  
  2933.     if ply.trade then
  2934.         Notify(ply, 3, 4, "You can't do this while trading")
  2935.         ply:InvRefresh()
  2936.         ply:GangStorageRefresh()
  2937.  
  2938.         return
  2939.     end
  2940.  
  2941.     -- race condition exploits
  2942.     if ply.RCExploit and ply.RCExploit > CurTime() then
  2943.         GangWars.Log("cheat", ply, "Blocked RC (GSADD)")
  2944.         ply:GangStorageRefresh()
  2945.         ply:InvRefresh()
  2946.         -- timer.Simple(1, function()
  2947.         -- ply:InvRefresh()
  2948.         -- end)
  2949.  
  2950.         return
  2951.     end
  2952.  
  2953.     ply.RCExploit = CurTime() + 2
  2954.  
  2955.     -- no storage until level 5
  2956.     if ply.GangInfo.level < 5 then
  2957.         Notify(ply, 3, 4, "You can't use gang storage until your gang is level 5")
  2958.         ply:GangStorageRefresh()
  2959.         ply:InvRefresh()
  2960.         -- timer.Simple(1, function()
  2961.         -- ply:InvRefresh()
  2962.         -- end)
  2963.  
  2964.         return
  2965.     end
  2966.  
  2967.     -- Note the player is dropping something
  2968.     ply.DroppingItem = true
  2969.     ply.trade = true
  2970.  
  2971.     -- Find the item
  2972.     GangWars.DBX.GetInventoryItem(ply, itemid, function(checkitem)
  2973.         if not checkitem then
  2974.             ply.DroppingItem = false
  2975.             ply.trade = false
  2976.  
  2977.             return
  2978.         end
  2979.  
  2980.         -- Can't drop credit items
  2981.         if checkitem.glon ~= "" and checkitem.glon ~= "nil" then
  2982.             local tmp = util.JSONToTable(checkitem.glon)
  2983.  
  2984.             if tmp.bound or tmp.superbound then
  2985.                 Notify(ply, 4, 4, "You can't put bound items in storage!")
  2986.                 ply:GangStorageRefresh()
  2987.                 ply:InvRefresh()
  2988.                 -- timer.Simple(1, function()
  2989.                 -- ply:InvRefresh()
  2990.                 -- end)
  2991.                 ply.DroppingItem = false
  2992.                 ply.trade = false
  2993.  
  2994.                 return
  2995.             end
  2996.         end
  2997.  
  2998.         -- do we have permission?
  2999.         local gang = ply.GangInfo.name
  3000.         local rank = ply:GetNW2Int("gang_rank")
  3001.  
  3002.         -- find permissions for the item
  3003.         isql:QueryValue("SELECT `permission` FROM `gw_gang_permissions` WHERE `gang` = " .. isql:Escape(gang) .. " AND `item` = 'storage_add';", function(perm)
  3004.             if not perm then
  3005.                 perm = 0
  3006.             end
  3007.  
  3008.             -- check our rank has permission to buy
  3009.             local function HasItemPerm(perms, rank)
  3010.                 local d = 16
  3011.                 local pms = {0, 0, 0, 0, 0}
  3012.                 local r = 5
  3013.  
  3014.                 while perms > 0 do
  3015.                     if perms - d >= 0 then
  3016.                         perms = perms - d
  3017.                         pms[r] = 1
  3018.                     end
  3019.  
  3020.                     d = d / 2
  3021.                     r = r - 1
  3022.                 end
  3023.  
  3024.                 return pms[rank] == 1
  3025.             end
  3026.  
  3027.             -- check our rank has permission to buy
  3028.             if not HasItemPerm(perm, rank) then
  3029.                 GangNotify(ply, 3, 4, "You don't have permission to add items to storage!")
  3030.                 ply:GangStorageRefresh()
  3031.                 ply:InvRefresh()
  3032.                 -- timer.Simple(1, function()
  3033.                 -- ply:InvRefresh()
  3034.                 -- end)
  3035.                 ply.DroppingItem = false
  3036.                 ply.trade = false
  3037.  
  3038.                 return
  3039.             end
  3040.  
  3041.             -- add item
  3042.             isql:Query("SELECT * FROM `gw_items` WHERE `steam` = " .. isql:Escape(steamID) .. " AND `id` = " .. isql:Escape(itemid), function(d, s, err)
  3043.                 d = d[1]
  3044.  
  3045.                 if not d then
  3046.                     ply:GangStorageRefresh()
  3047.                     ply:InvRefresh()
  3048.                     -- timer.Simple(1, function()
  3049.                     -- ply:InvRefresh()
  3050.                     -- end)
  3051.                     ply.DroppingItem = false
  3052.                     ply.trade = false
  3053.  
  3054.                     return
  3055.                 end
  3056.  
  3057.                 isql:Query("INSERT INTO `view_gang_storage` (`id`,`steam`, `class`,`ent`,`subclass`,`name`,`model`,`icon`,`value`,`quantity`,`level_lock`,`level`,`glon`,`slot`, `gang`) VALUES(" .. isql:Escape(d.id) .. "," .. isql:Escape(steamID) .. "," .. isql:Escape(d.class) .. "," .. isql:Escape(d.ent) .. "," .. isql:Escape(d.subclass) .. "," .. isql:Escape(d.name) .. "," .. isql:Escape(d.model) .. "," .. isql:Escape(d.icon) .. "," .. isql:Escape(d.value) .. "," .. isql:Escape(d.quantity) .. "," .. isql:Escape(d.level_lock) .. "," .. isql:Escape(d.level) .. "," .. isql:Escape(d.glon or {}) .. "," .. isql:Escape(slotid) .. "," .. isql:Escape(ply.GangInfo.name) .. ")", function(d, s, e)
  3058.                     isql:Query("DELETE FROM `gw_items` WHERE `steam` = " .. isql:Escape(steamID) .. " AND `id` = " .. isql:Escape(itemid), function(d, s, e)
  3059.                         GangWars.Log("gangstorage", ply, "{" .. ply:Gang() .. "} Added " .. checkitem.quantity .. "x" .. checkitem.name .. " [" .. checkitem.id .. "]")
  3060.                         ply:InvRefresh()
  3061.                         ply:AllGangStorageRefresh()
  3062.                         ply.DroppingItem = false
  3063.                         ply.trade = false
  3064.  
  3065.                         if not s then
  3066.                             Msg("GangWars.DBX.GangStorageAdd: Failed: " .. err .. "\n")
  3067.                         end
  3068.                     end)
  3069.                 end)
  3070.             end)
  3071.         end)
  3072.     end)
  3073. end
  3074.  
  3075. function GangWars.DBX.GangStorageRemove(ply, itemid, slot)
  3076.     if not IsValid(ply) or not ply.GangInfo then
  3077.         func(nil)
  3078.  
  3079.         return
  3080.     end
  3081.  
  3082.     local steamID = ply:SteamID()
  3083.  
  3084.     -- stop exploit where you drop an item & drop from storage
  3085.     if ply.DroppingItem or ply.upgrading then
  3086.         GangWars.Log("cheat", ply, "JIMMYS Gang Storage Exploit (GSTREM)") -- log jimmy lol
  3087.         ply:GangStorageRefresh()
  3088.         ply:InvRefresh()
  3089.         -- timer.Simple(1, function()
  3090.         -- ply:InvRefresh()
  3091.         -- end)
  3092.  
  3093.         return
  3094.     end
  3095.  
  3096.     if ply.trade then
  3097.         Notify(ply, 3, 4, "You can't do this while trading")
  3098.         ply:GangStorageRefresh()
  3099.         ply:InvRefresh()
  3100.         -- timer.Simple(1, function()
  3101.         -- ply:InvRefresh()
  3102.         -- end)
  3103.  
  3104.         return
  3105.     end
  3106.  
  3107.     -- race condition exploits
  3108.     if ply.RCExploit and ply.RCExploit > CurTime() then
  3109.         GangWars.Log("cheat", ply, "Blocked RC (GSREM)")
  3110.         ply:GangStorageRefresh()
  3111.         ply:InvRefresh()
  3112.         -- timer.Simple(1, function()
  3113.         -- ply:InvRefresh()
  3114.         -- end)
  3115.  
  3116.         return
  3117.     end
  3118.  
  3119.     ply.RCExploit = CurTime() + 2
  3120.     -- Note the player is dropping something
  3121.     ply.DroppingItem = true
  3122.     ply.trade = true
  3123.     -- do we have permission?
  3124.     local gang = ply.GangInfo.name
  3125.     local rank = ply:GetNW2Int("gang_rank")
  3126.  
  3127.     -- find permissions for the item
  3128.     isql:QueryValue("SELECT `permission` FROM `gw_gang_permissions` WHERE `gang` = " .. isql:Escape(gang) .. " AND `item` = 'storage_remove';", function(perm)
  3129.         if not perm then
  3130.             perm = 0
  3131.         end
  3132.  
  3133.         -- check our rank has permission to buy
  3134.         local function HasItemPerm(perms, rank)
  3135.             local d = 16
  3136.             local pms = {0, 0, 0, 0, 0}
  3137.             local r = 5
  3138.  
  3139.             while perms > 0 do
  3140.                 if perms - d >= 0 then
  3141.                     perms = perms - d
  3142.                     pms[r] = 1
  3143.                 end
  3144.  
  3145.                 d = d / 2
  3146.                 r = r - 1
  3147.             end
  3148.  
  3149.             return pms[rank] == 1
  3150.         end
  3151.  
  3152.         -- check our rank has permission to buy
  3153.         if not HasItemPerm(perm, rank) then
  3154.             GangNotify(ply, 3, 4, "You don't have permission to take items from storage!")
  3155.             ply:InvRefresh()
  3156.             ply:GangStorageRefresh()
  3157.             ply.DroppingItem = false
  3158.             ply.trade = false
  3159.  
  3160.             return
  3161.         end
  3162.  
  3163.         -- Check for inventory space
  3164.         if not ply:HasInvSpace() then
  3165.             Notify(ply, 3, 4, "Your inventory is full!")
  3166.             ply:InvRefresh()
  3167.             ply:GangStorageRefresh()
  3168.             ply.DroppingItem = false
  3169.             ply.trade = false
  3170.  
  3171.             return
  3172.         end
  3173.  
  3174.         -- Switch item to inventory
  3175.         isql:Query("SELECT * FROM `view_gang_storage` WHERE `id` = " .. isql:Escape(itemid) .. " AND `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(ply.GangInfo.name), function(d, s, err)
  3176.             d = d[1]
  3177.             local ciidata = GangWars.Item.FindByName(d.name):CreateCII()
  3178.             ciidata.glon = util.JSONToTable(d.glon)
  3179.             ciidata.value = d.value
  3180.             ciidata.quantity = d.quantity
  3181.             ciidata.level_lock = d.level_lock
  3182.             ciidata.level = d.level
  3183.  
  3184.             GangWars.DBX.AddInventoryItemCII(ply, ciidata, function(s)
  3185.                 if s then
  3186.                     isql:Query("DELETE FROM `view_gang_storage` WHERE `steam` = " .. isql:Escape(steamID) .. " AND `id` = " .. isql:Escape(itemid) .. " AND `gang` = " .. isql:Escape(ply.GangInfo.name), function(d, s, e)
  3187.                         ply:InvRefresh()
  3188.                         ply:AllGangStorageRefresh()
  3189.                         ply.DroppingItem = false
  3190.                         ply.trade = false
  3191.  
  3192.                         if not s then
  3193.                             Msg("GangWars.DBX.GangStorageRemove: Failed: " .. err .. "\n")
  3194.                         end
  3195.                     end)
  3196.                 end
  3197.             end, slot, false, true)
  3198.         end)
  3199.     end)
  3200. end
  3201.  
  3202. function GangWars.DBX.GangStorageMove(ply, itemid, slotid)
  3203.     if not IsValid(ply) or not ply.GangInfo then
  3204.         func(nil)
  3205.  
  3206.         return
  3207.     end
  3208.  
  3209.     local steamID = ply:SteamID()
  3210.  
  3211.     if ply.trade then
  3212.         Notify(ply, 3, 4, "You can't do this while trading")
  3213.         ply:GangStorageRefresh()
  3214.         ply:InvRefresh()
  3215.         -- timer.Simple(1, function()
  3216.         -- ply:InvRefresh()
  3217.         -- end)
  3218.  
  3219.         return
  3220.     end
  3221.  
  3222.     -- Switch item
  3223.     isql:Query("UPDATE `view_gang_storage` SET `slot` = " .. isql:Escape(slotid) .. " WHERE `id` = " .. isql:Escape(itemid) .. " AND `steam` = " .. isql:Escape(steamID) .. " AND `gang` = " .. isql:Escape(ply.GangInfo.name), function(d, s, err)
  3224.         ply:AllGangStorageRefresh()
  3225.  
  3226.         if not s then
  3227.             Msg("GangWars.DBX.GangStorageMove: Failed: " .. err .. "\n")
  3228.         end
  3229.     end)
  3230. end
  3231.  
  3232. --///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3233. -- Gang Storage Console Commands
  3234. local function DoStorageRefresh(ply, cmd, args)
  3235.     ply:GangStorageRefresh()
  3236.  
  3237.     return ""
  3238. end
  3239.  
  3240. concommand.Add("gang_storage_refresh", DoStorageRefresh)
  3241.  
  3242. local function DoStorageAdd(ply, cmd, args)
  3243.     local id = tonumber(args[1])
  3244.     local slot = tonumber(args[2])
  3245.     GangWars.DBX.GangStorageAdd(ply, id, slot)
  3246.  
  3247.     return ""
  3248. end
  3249.  
  3250. concommand.Add("gang_storage_add", DoStorageAdd)
  3251.  
  3252. local function DoStorageRemove(ply, cmd, args)
  3253.     local id = tonumber(args[1])
  3254.     local slot = tonumber(args[2])
  3255.     GangWars.DBX.GangStorageRemove(ply, id, slot)
  3256.  
  3257.     return ""
  3258. end
  3259.  
  3260. concommand.Add("gang_storage_remove", DoStorageRemove)
  3261.  
  3262. local function DoStorageMove(ply, cmd, args)
  3263.     local id = tonumber(args[1])
  3264.     local slot = tonumber(args[2])
  3265.     GangWars.DBX.GangStorageMove(ply, id, slot)
  3266.  
  3267.     return ""
  3268. end
  3269.  
  3270. concommand.Add("gang_storage_move", DoStorageMove)
  3271. util.AddNetworkString("gw_tg_request")
  3272. util.AddNetworkString("gw_tg_send")
  3273.  
  3274. net.Receive("gw_tg_request", function(l, p)
  3275.     local gdata = {}
  3276.     local cache = {}
  3277.     if p.LastGangScoreboardRequest and p.LastGangScoreboardRequest < CurTime() then return end
  3278.  
  3279.     isql:Query("SELECT `color`, `color2`, `name`, `level`, `points`, `money` FROM `gw_gangs` ORDER BY `points` DESC LIMIT 10", function(d, s, e)
  3280.         if s then
  3281.             table.insert(gdata, d)
  3282.  
  3283.             isql:Query("SELECT * FROM `gw_gang_members`", function(d2, s2, e2)
  3284.                 if s2 then
  3285.                     table.insert(cache, d2)
  3286.  
  3287.                     for index, gang in pairs(gdata) do
  3288.                         for ind, data in pairs(cache) do
  3289.                             if data.gang == gang.name then
  3290.                                 if not gdata[index]["players"] then
  3291.                                     gdata[index]["players"] = {}
  3292.                                 end
  3293.  
  3294.                                 table.insert(gdata[index]["players"], data)
  3295.                             end
  3296.                         end
  3297.  
  3298.                         if not gdata[index]["players"] then
  3299.                             gdata[index]["players"] = {}
  3300.                         end
  3301.                     end
  3302.                 end
  3303.  
  3304.                 net.Start("gw_tg_send")
  3305.                 net.WriteTable(gdata)
  3306.                 net.Send(p)
  3307.             end)
  3308.         end
  3309.     end)
  3310.  
  3311.     p.LastGangScoreboardRequest = CurTime() + 290
  3312. end)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top