@@ -12,14 +12,17 @@
if(check_canbuy && !can_buy(user, gang, gangtool))
return FALSE
var/real_cost = get_cost(user, gang, gangtool)
gang.adjust_influence(-real_cost)
spawn_item(user, gang, gangtool)
return TRUE
if(!spawn_item(user, gang, gangtool))
gang.adjust_influence(-real_cost)
to_chat(user, "<span class='notice'>You bought \the [name].</span>")
return TRUE

/datum/gang_item/proc/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
/datum/gang_item/proc/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool) // If this returns anything other than null, something fucked up and influence won't lower.
if(item_path)
var/obj/item/O = new item_path(user.loc)
user.put_in_hands(O)
else
return TRUE
if(spawn_msg)
to_chat(user, spawn_msg)

@@ -54,23 +57,31 @@
cost = 1

/datum/gang_item/clothing/under/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(gang.inner_outfit)
var/obj/item/O = new gang.inner_outfit(user.loc)
user.put_in_hands(O)
to_chat(user, "<span class='notice'> This is your gang's official uniform, wearing it will increase your influence")
if(gang.inner_outfits.len)
var/outfit = pick(gang.inner_outfits)
if(outfit)
var/obj/item/O = new outfit(user.loc)
user.put_in_hands(O)
to_chat(user, "<span class='notice'> This is your gang's official uniform, wearing it will increase your influence")
return
return TRUE

/datum/gang_item/clothing/suit
name = "Gang Armored Outerwear"
id = "suit"
cost = 1

/datum/gang_item/clothing/suit/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(gang.outer_outfit)
var/obj/item/O = new gang.outer_outfit(user.loc)
O.armor = list(melee = 20, bullet = 35, laser = 10, energy = 10, bomb = 30, bio = 0, rad = 0, fire = 30, acid = 30)
O.desc += " Tailored for the [gang.name] Gang to offer the wearer moderate protection against ballistics and physical trauma."
user.put_in_hands(O)
to_chat(user, "<span class='notice'> This is your gang's official outerwear, wearing it will increase your influence")
if(gang.outer_outfits.len)
var/outfit = pick(gang.outer_outfits)
if(outfit)
var/obj/item/O = new outfit(user.loc)
O.armor = list(melee = 20, bullet = 35, laser = 10, energy = 10, bomb = 30, bio = 0, rad = 0, fire = 30, acid = 30)
O.desc += " Tailored for the [gang.name] Gang to offer the wearer moderate protection against ballistics and physical trauma."
user.put_in_hands(O)
to_chat(user, "<span class='notice'> This is your gang's official outerwear, wearing it will increase your influence")
return
return TRUE


/datum/gang_item/clothing/hat
@@ -84,9 +95,6 @@
name = "pimpin' hat"
desc = "The undisputed king of style."

/obj/item/clothing/head/collectable/petehat/gang/gang_contraband_value()
return 4

/datum/gang_item/clothing/mask
name = "Golden Death Mask"
id = "mask"
@@ -97,10 +105,6 @@
name = "golden death mask"
icon_state = "gskull"
desc = "Strike terror, and envy, into the hearts of your enemies."
species_restricted = list("exclude","Vox Outcast")

/obj/item/clothing/mask/gskull/gang_contraband_value()
return 5

/datum/gang_item/clothing/shoes
name = "Bling Boots"
@@ -112,10 +116,6 @@
name = "blinged-out boots"
desc = "Stand aside peasants."
icon_state = "bling"
species_restricted = list("exclude","Vox Outcast")

/obj/item/clothing/shoes/gang/gang_contraband_value()
return 6

/datum/gang_item/clothing/neck
name = "Gold Necklace"
@@ -135,9 +135,6 @@
icon_state = "knuckles"
w_class = 3

/obj/item/clothing/gloves/gang/gang_contraband_value()
return 3

/datum/gang_item/clothing/belt
name = "Badass Belt"
id = "belt"
@@ -149,10 +146,6 @@
icon_state = "gangbelt"
item_state = "gang"
desc = "The belt buckle simply reads 'BAMF'."
storage_slots = 1

/obj/item/storage/belt/military/gang/gang_contraband_value()
return 4

///////////////////
//WEAPONS
@@ -163,9 +156,6 @@

/datum/gang_item/weapon/ammo

/datum/gang_item/weapon/ammo/get_cost_display(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
return "&nbsp;&#8627;" + ..() //this is pretty hacky but it looks nice on the popup

/datum/gang_item/weapon/shuriken
name = "Shuriken"
id = "shuriken"
@@ -214,8 +204,6 @@
cost = 10
item_path = /obj/item/ammo_box/magazine/m10mm



/datum/gang_item/weapon/machinegun
name = "Mounted Machine Gun"
id = "MG"
@@ -249,6 +237,10 @@
cost = 5
item_path = /obj/item/toy/crayon/spraycan/gang

/datum/gang_item/equipment/spraycan/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
var/obj/item/O = new item_path(user.loc, gang)
user.put_in_hands(O)

/datum/gang_item/equipment/sharpener
name = "Sharpener"
id = "whetstone"
@@ -288,11 +280,8 @@
spawn_msg = "<span class='notice'>The <b>implant breaker</b> is a single-use device that destroys all implants within the target before trying to recruit them to your gang. Also works on enemy gangsters.</span>"

/datum/gang_item/equipment/implant_breaker/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(item_path)
var/obj/item/O = new item_path(user.loc, gang) //we need to override this whole proc for this one argument
user.put_in_hands(O)
if(spawn_msg)
to_chat(user, spawn_msg)
var/obj/item/O = new item_path(user.loc, gang)
user.put_in_hands(O)

/datum/gang_item/equipment/wetwork_boots
name = "Wetwork boots"
@@ -336,21 +325,20 @@

/datum/gang_item/equipment/gangtool/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
var/item_type
if(gang && (user.mind in gang.leaders))
if(gang)
item_type = /obj/item/device/gangtool/spare/lt
if(gang.leaders.len < 3)
to_chat(user, "<span class='notice'><b>Gangtools</b> allow you to promote a gangster to be your Lieutenant, enabling them to recruit and purchase items like you. Simply have them register the gangtool. You may promote up to [3-gang.bosses.len] more Lieutenants</span>")
if(gang.leaders.len < MAX_LEADERS_GANG)
to_chat(user, "<span class='notice'><b>Gangtools</b> allow you to promote a gangster to be your Lieutenant, enabling them to recruit and purchase items like you. Simply have them register the gangtool. You may promote up to [MAX_LEADERS_GANG-gang.leaders.len] more Lieutenants</span>")
else
item_type = /obj/item/device/gangtool/spare
var/obj/item/device/gangtool/spare/tool = new item_type(user.loc)
user.put_in_hands(tool)

/datum/gang_item/equipment/gangtool/get_name_display(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(gang && isboss(user, gang) && (gang.bosses.len < 3))
if(gang && (gang.leaders.len < gang.max_leaders))
return "Promote a Gangster"
return "Spare Gangtool"


/datum/gang_item/equipment/dominator
name = "Station Dominator"
id = "dominator"
@@ -361,6 +349,10 @@
/datum/gang_item/equipment/dominator/can_buy(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(!gang || !gang.dom_attempts)
return FALSE
var/area/userarea = get_area(user)
if(userarea.type in gang.territories|gang.new_territories)
to_chat(user,"<span class='warning'>The <b>dominator</b> can be spawned only on territory controlled by your gang!</span>")
return FALSE
return ..()

/datum/gang_item/equipment/dominator/get_name_display(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
@@ -375,28 +367,17 @@

/datum/gang_item/equipment/dominator/get_extra_info(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
if(gang)
return "(Estimated Takeover Time: [round(determine_domination_time(gang)/60,0.1)] minutes)"
return "This device requires a 5x5 area clear of walls to work. (Estimated Takeover Time: [round(gang.determine_domination_time()/60,0.1)] minutes)"

/datum/gang_item/equipment/dominator/purchase(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
var/area/usrarea = get_area(user.loc)
var/usrturf = get_turf(user.loc)
if(initial(usrarea.name) == "Space" || isspaceturf(usrturf) || !is_station_level(user.z))
to_chat(user, "<span class='warning'>You can only use this on the station!</span>")
return FALSE

for(var/obj/obj in usrturf)
for(var/obj/obj in get_turf(user))
if(obj.density)
to_chat(user, "<span class='warning'>There's not enough room here!</span>")
return FALSE

if(dominator_excessive_walls(user))
to_chat(user, "<span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires a sizable open space within three standard units so that walls do not interfere with the signal.</span>")
return FALSE

if(!(usrarea.type in gang.territories|gang.territories_new))
to_chat(user, "<span class='warning'>The <b>dominator</b> can be spawned only on territory controlled by your gang!</span>")
return FALSE
return ..()

/datum/gang_item/equipment/dominator/spawn_item(mob/living/carbon/user, datum/team/gang/gang, obj/item/device/gangtool/gangtool)
new item_path(user.loc)
new item_path(user.loc)
to_chat(user, spawn_msg)
@@ -5,7 +5,7 @@
var/cooldown
var/last_used

/obj/item/pen/gang/New()
/obj/item/pen/gang/Initialize()
..()
last_used = world.time

@@ -22,11 +22,11 @@
if(cooldown)
to_chat(user, "<span class='warning'>[src] needs more time to recharge before it can be used.</span>")
return
if(!M.client)
if(!M.client || !M.mind)
to_chat(user, "<span class='warning'>A braindead gangster is an useless gangster!</span>")
return
var/datum/team/gang/gang = L.gang
something_that_makes_this_dude_a_gangster()
add_gangster(user, gang, M.mind)
cooldown = TRUE
icon_state = "pen_blink"
var/cooldown_time = 600+(600*gang.leaders.len)
@@ -37,4 +37,22 @@
icon_state = "pen"
var/mob/M = loc
if(istype(M))
to_chat(M, "<span class='notice'>[icon2html(src, M)] [src][(loc == M)?(""):(" in your [loc]")] vibrates softly. It is ready to be used again.</span>")
to_chat(M, "<span class='notice'>[icon2html(src, M)] [src][(loc == M)?(""):(" in your [loc]")] vibrates softly. It is ready to be used again.</span>")

/obj/item/pen/gang/proc/add_gangster(mob/user, datum/team/gang/gang, datum/mind/gangster_mind, check = TRUE) // Basically a wrapper to add_antag_datum.
var/datum/antagonist/dudegang = gangster_mind.has_antag_datum(/datum/antagonist/gang)
if(dudegang)
if(dudegang == gang)
to_chat(user, "<span class='danger'>This mind is already controlled by your gang!</span>")
return
to_chat(user, "<span class='danger'>This mind is already controlled by someone else!</span>")
return
if(check && gangster_mind.current.isloyal()) //Check to see if the potential gangster is implanted
to_chat(user, "<span class='danger'>This mind is too strong to control!</span>")
return
var/mob/living/carbon/human/H = gangster_mind.current // we are sure the dude's human cause it's checked in attack()
H.silent = max(H.silent, 5)
H.Stun(100)
if(jobban_isbanned(gangster_mind.current, ROLE_GANG))
INVOKE_ASYNC(src, /datum/game_mode.proc/replace_jobbaned_player, gangster_mind.current, ROLE_GANG, ROLE_GANG) // will gangster_mind point to the new dude's mind? dunno honestly, i hope it does
gangster_mind.add_antag_datum(/datum/antagonist/gang, gang)
@@ -7,8 +7,8 @@ GLOBAL_LIST_EMPTY(gangs)
config_tag = "gang"
antag_flag = ROLE_GANG
restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
required_players = 15
required_enemies = 2
required_players = 1 //15
required_enemies = 1 // 2
recommended_enemies = 2
enemy_minimum_age = 14

@@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(gangs)
restricted_jobs += "Assistant"

//Spawn more bosses depending on server population
var/gangs_to_create = 2
var/gangs_to_create = 1//2
if(prob(num_players()) && num_players() > 1.5*required_players)
gangs_to_create++
if(prob(num_players()) && num_players() > 2*required_players)
@@ -45,22 +45,20 @@ GLOBAL_LIST_EMPTY(gangs)
gangboss_candidates += boss
boss.restricted_roles = restricted_jobs

if(gangboss_candidates.len < 2) //Need at least two gangs
return 0
if(gangboss_candidates.len < 1) //Need at least two gangs
return

return 1
return TRUE


/datum/game_mode/gang/post_setup()
set waitfor = FALSE
..()
for(var/i in gangboss_candidates)
var/datum/mind/M = i
var/datum/team/gang/grove = pick_n_take(GLOB.possible_gangs)
if(grove)
grove = new(M) // by passing M, it also makes M a boss and gives him the boss stuff
gangs += grove
else break
var/datum/antagonist/gang/boss/B = new()
M.add_antag_datum(B)
B.equip_gang()


/datum/game_mode/proc/forge_gang_objectives(datum/mind/boss_mind)
@@ -83,10 +81,6 @@ GLOBAL_LIST_EMPTY(gangs)
SSshuttle.emergency.request(null, set_coefficient = 0.4)
priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.")

/proc/determine_domination_time(var/datum/team/gang/G)
return max(180,480 - (round((G.territories.len/GLOB.start_state.num_territories)*100, 1) * 9))


//////////////////////////////////////////////////////////////////////
//Announces the end of the game with all relavent information stated//
//////////////////////////////////////////////////////////////////////
@@ -115,26 +109,3 @@ GLOBAL_LIST_EMPTY(gangs)
text += printplayer(gangster, 1)
text += "<br>"
to_chat(world, text)

//////////////////////////////////////////////////////////
//Handles influence, territories, and the victory checks//
//////////////////////////////////////////////////////////


/datum/game_mode/gang/generate_credit_text()
var/list/round_credits = list()
var/len_before_addition

for(var/datum/team/gang/G in gangs)
round_credits += "<center><h1>The [G.name] Gang:</h1>"
len_before_addition = round_credits.len
for(var/datum/mind/boss in G.leaders)
round_credits += "<center><h2>[boss.name] as a [G.name] Gang leader</h2>"
for(var/datum/mind/gangster in G.members - G.leaders)
round_credits += "<center><h2>[gangster.name] as a [G.name] gangster</h2>"
if(len_before_addition == round_credits.len)
round_credits += list("<center><h2>The [G.name] Gang was wiped out!</h2>", "<center><h2>The competition was too tough!</h2>")
round_credits += "<br>"

round_credits += ..()
return round_credits
@@ -2,7 +2,8 @@
/obj/item/device/gangtool
name = "suspicious device"
desc = "A strange device of sorts. Hard to really make out what it actually does if you don't know how to operate it."
icon_state = "gangtool-white"
icon = 'hippiestation/icons/obj/device.dmi'
icon_state = "gangtool"
item_state = "radio"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
@@ -15,9 +16,27 @@
var/recalling = 0
var/outfits = 2
var/free_pen = 0
var/promotable = 0
var/promotable = FALSE
var/static/list/buyable_items = list()
var/list/tags = list()

/obj/item/device/gangtool/Initialize()
..()
update_icon()
for(var/i in subtypesof(/datum/gang_item))
var/datum/gang_item/G = i
var/id = initial(G.id)
var/cat = initial(G.category)
if(id)
if(!islist(buyable_items[cat]))
buyable_items[cat] = list()
buyable_items[cat][id] = new G

/obj/item/device/gangtool/Destroy()
if(gang)
gang.gangtools -= src
return ..()

/obj/item/device/gangtool/attack_self(mob/user)
..()
if (!can_use(user))
@@ -44,17 +63,15 @@
dat += "<center><font color='red'>Takeover In Progress:<br><B>[gang.domination_time] seconds remain</B></font></center>"

dat += "Registration: <B>[gang.name] Gang Boss</B><br>"
dat += "Organization Size: <B>[gang.members.len]</B> | Station Control: <B>[gang.territories.len] territories under control.</B><br>"
dat += "Organization Size: <B>[gang.members.len]</B> | Station Control: <B>[gang.territories.len] territories under control.</B> | Influence: <B>[gang.influence]</B><br>"
dat += "Time until Influence grows: <B>[time2text(gang.next_point_time - world.time, "mm:ss")]</B><br>"
dat += "<a href='?src=[REF(src)];commute=1'>Send message to Gang</a><br>"
dat += "<a href='?src=[REF(src)];recall=1'>Recall shuttle</a><br>"
dat += "<hr>"
if(!islist(gang.buyable_items))
gang.set_gang_item_list()
for(var/cat in gang.buyable_items)
for(var/cat in buyable_items)
dat += "<b>[cat]</b><br>"
for(var/V in gang.buyable_items[cat])
var/datum/gang_item/G = V
for(var/id in buyable_items[cat])
var/datum/gang_item/G = buyable_items[cat][id]
if(!G.can_see(user, gang, src))
continue

@@ -64,7 +81,7 @@

var/toAdd = G.get_name_display(user, gang, src)
if(G.can_buy(user, gang, src))
toAdd = "<a href='?src=[REF(src)];purchase=[G.id]'>[toAdd]</a>"
toAdd = "<a href='?src=[REF(src)];purchase=1;id=[id];cat=[cat]'>[toAdd]</a>"
dat += toAdd
var/extra = G.get_extra_info(user, gang, src)
if(extra)
@@ -78,8 +95,6 @@
popup.set_content(dat)
popup.open()



/obj/item/device/gangtool/Topic(href, href_list)
if(!can_use(usr))
return
@@ -93,19 +108,27 @@
return

if(href_list["purchase"])
var/datum/gang_item/G = gang.boss_item_list[href_list["purchase"]]
if(G && G.can_buy(usr, gang, src))
G.purchase(usr, gang, src, FALSE)
if(islist(buyable_items[href_list["cat"]]))
var/list/L = buyable_items[href_list["cat"]]
var/datum/gang_item/G = L[href_list["id"]]
if(G && G.can_buy(usr, gang, src))
G.purchase(usr, gang, src, FALSE)

if(href_list["commute"])
ping_gang(usr)
if(href_list["recall"])
recall(usr)
attack_self(usr)

/obj/item/device/gangtool/update_icon()
overlays.Cut()
var/image/I = new(icon, "[icon_state]-overlay")
if(gang)
I.color = gang.color
overlays.Add(I)

/obj/item/device/gangtool/proc/ping_gang(mob/user)
if(!user)
if(!can_use(user))
return
var/message = stripped_input(user,"Discreetly send a gang-wide message.","Send Message") as null|text
if(!message || !can_use(user))
@@ -114,7 +137,7 @@
to_chat(user, "<span class='info'>[icon2html(src, user)]Error: Station out of range.</span>")
return
if(gang.members.len)
var/ping = "<span class='danger'><B><i>[gang.name] [user in gang.leaders ? "Leader" : "Gangster"]</i>: [message]</B></span>"
var/ping = "<span class='danger'><B><i>[gang.name] [(user.mind in gang.leaders) ? "Leader" : "Gangster"]</i>: [message]</B></span>"
for(var/datum/mind/ganger in gang.members)
if(ganger.current && is_station_level(ganger.current.z) && (ganger.current.stat == CONSCIOUS))
to_chat(ganger.current, ping)
@@ -123,16 +146,15 @@
to_chat(M, "[link] [ping]")
log_talk(user,"GANG: [key_name(user)] Messaged [gang.name] Gang: [message].",LOGSAY)


/obj/item/device/gangtool/proc/register_device(mob/user)
if(gang) //It's already been registered!
return
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang, FALSE)
if((promotable && G) || (user.mind.has_antag_datum(/datum/antagonist/gang/boss)))
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
if(G)
gang = G.gang
gang.gangtools += src
icon_state = "gangtool-[gang.color]"// todo- replace this with normal gangtool + colored overlay
if(!(user.mind in gang.leaders))// replace gang datum with boss datum! todo
update_icon()
if(!(user.mind in gang.leaders) && promotable)
G.promote()
free_pen = TRUE
gang.message_gangtools("[user] has been promoted to Lieutenant.")
@@ -174,14 +196,16 @@
recalling = FALSE
return

var/turf/userturf = get_turf(user)
if(is_station_level(userturf.z)) //Shuttle can only be recalled while on station
if(!is_station_level(user.z)) //Shuttle can only be recalled while on station
to_chat(user, "<span class='warning'>[icon2html(src, user)]Error: Device out of range of station communication arrays.</span>")
recalling = FALSE
return
var/datum/station_state/end_state = new /datum/station_state()
end_state.count()
if((100 * GLOB.start_state.score(end_state)) < 80) //Shuttle cannot be recalled if the station is too damaged
var/list/living_crew = list()//shamelessly copied from mulligan code, there should be a helper for this
for(var/mob/Player in GLOB.mob_list)
if(Player.mind && Player.stat != DEAD && !isnewplayer(Player) && !isbrain(Player) && Player.client)
living_crew += Player
var/malc = CONFIG_GET(number/midround_antag_life_check)
if(living_crew.len / GLOB.joined_player_list.len <= malc) //Shuttle cannot be recalled if too many people died
to_chat(user, "<span class='warning'>[icon2html(src, user)]Error: Station communication systems compromised. Unable to establish connection.</span>")
recalling = FALSE
return
@@ -202,19 +226,21 @@

/obj/item/device/gangtool/proc/can_use(mob/living/carbon/human/user)
if(!istype(user))
return 0
return
if(user.incapacitated())
return 0
return
if(!(src in user.contents))
return 0
return
if(!user.mind)
return 0
if(gang && (user.mind in gang.leaders)) //If it's already registered, only let the gang's bosses use this
return 1
return 0
return
if(!user.mind.has_antag_datum(/datum/antagonist/gang))
to_chat(user, "<span class='notice'>Huh, what's this?</span>")
return
return TRUE


/obj/item/device/gangtool/spare
outfits = 1
outfits = TRUE

/obj/item/device/gangtool/spare/lt
promotable = 1
promotable = TRUE
@@ -7,7 +7,7 @@
var/obj/machinery/dominator/D = attached_to
if(!istype(D))
return
else if(D.gang && D.gang.domination_time != -1)
else if(D.gang && D.gang.domination_time != NOT_DOMINATING)
return D.gang.domination_time
else
return "OFFLINE"
@@ -0,0 +1,26 @@
/obj/effect/decal/cleanable/crayon/gang
icon = 'hippiestation/icons/effects/crayondecal.dmi'
layer = HIGH_OBJ_LAYER //Harder to hide
plane = GAME_PLANE
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
var/datum/team/gang/gang

/obj/effect/decal/cleanable/crayon/gang/Initialize(mapload, datum/team/gang/G, e_name = "gang tag", rotation = 0, mob/user)
if(!G)
qdel(src)
return
gang = G
var/newcolor = G.color
var/area/territory = get_area(src)
icon_state = G.name
G.new_territories |= list(territory.type = territory.name)
//If this isn't tagged by a specific gangster there's no bonus income.
..(mapload, newcolor, icon_state, e_name, rotation)

/obj/effect/decal/cleanable/crayon/gang/Destroy()
if(gang)
var/area/territory = get_area(src)
gang.territories -= territory.type
gang.new_territories -= territory.type
gang.lost_territories |= list(territory.type = territory.name)
return ..()
@@ -1,17 +1,161 @@
#define RANDOM_GRAFFITI "Random Graffiti"
#define RANDOM_LETTER "Random Letter"
#define RANDOM_NUMBER "Random Number"
#define RANDOM_ORIENTED "Random Oriented"
#define RANDOM_RUNE "Random Rune"
#define RANDOM_ANY "Random Anything"

/obj/item/toy/crayon
var/gang = FALSE //For marking territory
var/datum/team/gang/gang //For marking territory, spraycans are gang-locked to their initial gang due to colors

/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity, params)
if(!proximity || !check_allowed_items(target))
return

var/cost = 1
if(paint_mode == PAINT_LARGE_HORIZONTAL)
cost = 5
if(istype(target, /obj/item/canvas))
cost = 0

if(istype(target, /obj/effect/decal/cleanable))
target = target.loc

if(!is_type_in_list(target,validSurfaces))
return

var/drawing = drawtype
switch(drawtype)
if(RANDOM_LETTER)
drawing = pick(letters)
if(RANDOM_GRAFFITI)
drawing = pick(graffiti)
if(RANDOM_RUNE)
drawing = pick(runes)
if(RANDOM_ORIENTED)
drawing = pick(oriented)
if(RANDOM_NUMBER)
drawing = pick(numerals)
if(RANDOM_ANY)
drawing = pick(all_drawables)

var/temp = "rune"
if(drawing in letters)
temp = "letter"
else if(drawing in graffiti)
temp = "graffiti"
else if(drawing in numerals)
temp = "number"

temp = hippie_gang_check(user,target)
if(!temp) return // hippie
var/graf_rot
if(drawing in oriented)
switch(user.dir)
if(EAST)
graf_rot = 90
if(SOUTH)
graf_rot = 180
if(WEST)
graf_rot = 270
else
graf_rot = 0

var/list/click_params = params2list(params)
var/clickx
var/clicky

if(click_params && click_params["icon-x"] && click_params["icon-y"])
clickx = CLAMP(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2)
clicky = CLAMP(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2)

if(!instant)
to_chat(user, "<span class='notice'>You start drawing a [temp] on the [target.name]...</span>")

if(pre_noise)
audible_message("<span class='notice'>You hear spraying.</span>")
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)

var/takes_time = !instant

var/wait_time = 50
if(paint_mode == PAINT_LARGE_HORIZONTAL)
wait_time *= 3
if(gang) takes_time = TRUE // hippie
if(takes_time)
if(!do_after(user, 50, target = target))
return

if(length(text_buffer))
drawing = copytext(text_buffer,1,2)


var/list/turf/affected_turfs = list()

if(!gang) // hippie - drawing is done in gang_final() if it's a gang type
if(actually_paints)
switch(paint_mode)
if(PAINT_NORMAL)
var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot)
C.add_hiddenprint(user)
C.pixel_x = clickx
C.pixel_y = clicky
affected_turfs += target
if(PAINT_LARGE_HORIZONTAL)
var/turf/left = locate(target.x-1,target.y,target.z)
var/turf/right = locate(target.x+1,target.y,target.z)
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
C.add_hiddenprint(user)
affected_turfs += left
affected_turfs += right
affected_turfs += target
else
to_chat(user, "<span class='warning'>There isn't enough space to paint!</span>")
return
else // hippie
if(gang_final(user, target, affected_turfs)) return // hippie

if(!instant)
to_chat(user, "<span class='notice'>You finish drawing \the [temp].</span>")
else
to_chat(user, "<span class='notice'>You spray a [temp] on \the [target.name]</span>")

var/charges_used = use_charges(user, cost)
if(!charges_used)
return
. = charges_used

if(length(text_buffer))
text_buffer = copytext(text_buffer,2)

if(post_noise)
audible_message("<span class='notice'>You hear spraying.</span>")
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)

var/fraction = min(1, . / reagents.maximum_volume)
if(affected_turfs.len)
fraction /= affected_turfs.len
for(var/t in affected_turfs)
reagents.reaction(t, TOUCH, fraction * volume_multiplier)
reagents.trans_to(t, ., volume_multiplier)
check_empty(user)

/obj/item/toy/crayon/proc/hippie_gang_check(mob/user, atom/target) // hooked into afterattack
// If a gang member is using a gang spraycan, it'll behave differently
var/gang_mode = FALSE
if(gang && user.mind && user.mind.has_antag_datum(/datum/antagonist/gang))
if(gang && user.mind)
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
if(G.gang != gang)
to_chat(user, "<span class='danger'>This spraycan's color isn't your gang's one! You cannot use it.</span>")
return FALSE
gang_mode = TRUE

instant = FALSE
. = "graffiti"
// discontinue if the area isn't valid for tagging because gang "honour"
if(gang_mode && (!can_claim_for_gang(user, target)))
return TRUE
return FALSE

/obj/item/toy/crayon/proc/gang_final(mob/user, atom/target) // hooked into afterattack
/obj/item/toy/crayon/proc/gang_final(mob/user, atom/target, list/affected_turfs) // hooked into afterattack
// Double check it wasn't tagged in the meanwhile
if(!can_claim_for_gang(user, target))
return TRUE
@@ -28,9 +172,12 @@

var/spraying_over = FALSE
for(var/G in target)
if(istype(G, /obj/effect/decal/cleanable/crayon/gang))
spraying_over = TRUE
break
var/obj/effect/decal/cleanable/crayon/gang/gangtag = G
if(istype(gangtag))
var/datum/antagonist/gang/GA = user.mind.has_antag_datum(/datum/antagonist/gang)
if(gangtag.gang != GA.gang)
spraying_over = TRUE
break

for(var/obj/machinery/power/apc in target)
to_chat(user, "<span class='warning'>You can't tag an APC.</span>")
@@ -55,10 +202,10 @@
for(var/obj/effect/decal/cleanable/crayon/old_marking in target)
qdel(old_marking)

var/gangID = user.mind.has_antag_datum(/datum/antagonist/gang)
var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang)
var/area/territory = get_area(target)

new /obj/effect/decal/cleanable/crayon/gang(target,gangID,"graffiti",0,user)
new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user)
to_chat(user, "<span class='notice'>You tagged [territory] for your gang!</span>")

/obj/item/toy/crayon/spraycan/gang
@@ -72,10 +219,18 @@
/obj/item/toy/crayon/spraycan/gang/Initialize(loc, datum/team/gang/G)
..()
if(G)
gang = G
paint_color = G.color
update_icon()

/obj/item/toy/crayon/spraycan/gang/examine(mob/user)
. = ..()
if(user.mind && user.mind.has_antag_datum(/datum/antagonist/gang) || isobserver(user))
to_chat(user, "This spraycan has been specially modified for tagging territory.")
to_chat(user, "This spraycan has been specially modified for tagging territory.")

#undef RANDOM_GRAFFITI
#undef RANDOM_LETTER
#undef RANDOM_NUMBER
#undef RANDOM_ORIENTED
#undef RANDOM_RUNE
#undef RANDOM_ANY
@@ -0,0 +1,14 @@
/datum/station_state
var/num_territories = 1//Number of total valid territories for gang mode

/datum/station_state/count(count_territories)
..()
if(count_territories)
var/list/valid_territories = list()
for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) //First, collect all area types on the station zlevel
for(var/ar in SSmapping.areas_in_z["[z]"])
var/area/A = ar
if(!(A.type in valid_territories) && A.valid_territory)
valid_territories |= A.type
if(valid_territories.len)
num_territories = valid_territories.len //Add them all up to make the total number of area types

Large diffs are not rendered by default.

@@ -0,0 +1,98 @@

// Gang datums go here. If you want to create a new gang, you must be sure to edit:
// name
// color (must be a hex, "blue" isn't acceptable due to how spraycans are handled)
// inner_outfits (must be a list() with typepaths of the clothes in it. One is fine, but there is support for multiple: one will be picked at random when bought)
// outer_outfits (same as above)
// Those are all required. If one is missed, stuff could break.

/datum/team/gang/clandestine
name = "Clandestine"
color = "#FF0000"
inner_outfits = list(/obj/item/clothing/under/color/red)
outer_outfits = list(/obj/item/clothing/suit/jacket/leather)

/datum/team/gang/prima
name = "Prima"
color = "#FFFF00"
inner_outfits = list(/obj/item/clothing/under/color/yellow)

/datum/team/gang/zerog
name = "Zero-G"
color = "#C0C0C0"

/datum/team/gang/max
name = "Max"
color = "#800000"

/datum/team/gang/blasto
name = "Blasto"
color = "#000080"

/datum/team/gang/waffle
name = "Waffle"
color = "#808000"

/datum/team/gang/north
name = "North"
color = "#00FF00"

/datum/team/gang/omni
name = "Omni"
color = "#008080"

/datum/team/gang/newton
name = "Newton"
color = "#00FFFF"

/datum/team/gang/cyber
name = "Cyber"
color = "#808000"

/datum/team/gang/donk
name = "Donk"
color = "#0000FF"

/datum/team/gang/gene
name = "Gene"
color = "#00FFFF"

/datum/team/gang/gib
name = "Gib"
color = "#000000"

/datum/team/gang/tunnel
name = "Tunnel"
color = "#FF00FF"

/datum/team/gang/diablo
name = "Diablo"
color = "#FF00FF"

/datum/team/gang/psyke
name = "Psyke"
color = "#808080"

/datum/team/gang/osiron
name = "Osiron"
color = "#FFFFFF"

/datum/team/gang/sirius
name = "Sirius"
color = "#800080"

/datum/team/gang/sleepingcarp
name = "Sleeping Carp"
color = "#00C000"

/datum/team/gang/h
name = "H"
color = "#993333"

/datum/team/gang/rigatonifamily
name = "Rigatoni family"
color = "#cc9900" // p a s t a colored

/datum/team/gang/weed
name = "Weed"
color = "#66ff33"
Binary file not shown.
BIN +450 Bytes (120%) hippiestation/icons/obj/device.dmi
Binary file not shown.