diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index ac7589364c6..a16d120bb4d 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -30,8 +30,7 @@
var/newscaster_announcements = null
var/ert_disabled = 0
var/uplink_welcome = "Syndicate Uplink Console:"
- var/uplink_uses = 10
- var/datum/cult_info/cultdat = new /datum/cult_info() //here instead of cult for adminbus purposes
+ var/uplink_uses = 20
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
@@ -54,16 +53,11 @@
//pre_pre_setup() For when you really don't want certain jobs ingame.
/datum/game_mode/proc/pre_pre_setup()
-
return 1
///pre_setup()
///Attempts to select players for special roles the mode might have.
/datum/game_mode/proc/pre_setup()
- cultdat = pick(all_cults)
- if(!cultdat)
- to_chat(world, "Failed to select a cult datum, Shank a coder.")
- return 0
return 1
diff --git a/code/game/gamemodes/game_mode2.dm b/code/game/gamemodes/game_mode2.dm
new file mode 100644
index 00000000000..030b9a08012
--- /dev/null
+++ b/code/game/gamemodes/game_mode2.dm
@@ -0,0 +1,477 @@
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+
+/*
+ * GAMEMODES (by Rastaf0)
+ *
+ * In the new mode system all special roles are fully supported.
+ * You can have proper wizards/traitors/changelings/cultists during any mode.
+ * Only two things really depends on gamemode:
+ * 1. Starting roles, equipment and preparations
+ * 2. Conditions of finishing the round.
+ *
+ */
+
+
+/datum/game_mode
+ var/name = "invalid"
+ var/config_tag = null
+ var/intercept_hacked = 0
+ var/votable = 1
+ var/probability = 0
+ var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm
+ var/explosion_in_progress = 0 //sit back and relax
+ var/list/datum/mind/modePlayer = new
+ var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist
+ var/list/protected_jobs = list() // Jobs that can't be traitors
+ var/list/protected_species = list() // Species that can't be traitors
+ var/required_players = 0
+ var/required_enemies = 0
+ var/recommended_enemies = 0
+ var/newscaster_announcements = null
+ var/ert_disabled = 0
+ var/uplink_welcome = "Syndicate Uplink Console:"
+ var/uplink_uses = 10
+ var/datum/cult_info/cultdat = new /datum/cult_info() //here instead of cult for adminbus purposes
+
+ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
+ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
+
+/datum/game_mode/proc/announce() //to be calles when round starts
+ to_chat(world, "Notice: [src] did not define announce()")
+
+
+///can_start()
+///Checks to see if the game can be setup and ran with the current number of players or whatnot.
+/datum/game_mode/proc/can_start()
+ var/playerC = 0
+ for(var/mob/new_player/player in player_list)
+ if((player.client)&&(player.ready))
+ playerC++
+
+ if(playerC >= required_players)
+ return 1
+ return 0
+
+//pre_pre_setup() For when you really don't want certain jobs ingame.
+/datum/game_mode/proc/pre_pre_setup()
+
+ return 1
+
+///pre_setup()
+///Attempts to select players for special roles the mode might have.
+/datum/game_mode/proc/pre_setup()
+ cultdat = pick(all_cults)
+ if(!cultdat)
+ to_chat(world, "Failed to select a cult datum, Shank a coder.")
+ return 0
+ return 1
+
+
+///post_setup()
+///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
+/datum/game_mode/proc/post_setup()
+ spawn (ROUNDSTART_LOGOUT_REPORT_TIME)
+ display_roundstart_logout_report()
+
+ feedback_set_details("round_start","[time2text(world.realtime)]")
+ if(ticker && ticker.mode)
+ feedback_set_details("game_mode","[ticker.mode]")
+// if(revdata)
+// feedback_set_details("revision","[revdata.revision]")
+ feedback_set_details("server_ip","[world.internet_address]:[world.port]")
+ start_state = new /datum/station_state()
+ start_state.count()
+ return 1
+
+
+///process()
+///Called by the gameticker
+/datum/game_mode/proc/process()
+ return 0
+
+//Called by the gameticker
+/datum/game_mode/proc/process_job_tasks()
+ var/obj/machinery/message_server/useMS = null
+ if(message_servers)
+ for (var/obj/machinery/message_server/MS in message_servers)
+ if(MS.active)
+ useMS = MS
+ break
+ for(var/mob/M in player_list)
+ if(M.mind)
+ var/obj/item/device/pda/P=null
+ for(var/obj/item/device/pda/check_pda in PDAs)
+ if (check_pda.owner==M.name)
+ P=check_pda
+ break
+ var/count=0
+ for(var/datum/job_objective/objective in M.mind.job_objectives)
+ count++
+ var/msg=""
+ var/pay=0
+ if(objective.per_unit && objective.units_compensated0)
+ if(M.mind.initial_account)
+ M.mind.initial_account.money += pay
+ var/datum/transaction/T = new()
+ T.target_name = "[command_name()] Payroll"
+ T.purpose = "Payment"
+ T.amount = pay
+ T.date = current_date_string
+ T.time = worldtime2text()
+ T.source_terminal = "\[CLASSIFIED\] Terminal #[rand(111,333)]"
+ M.mind.initial_account.transaction_log.Add(T)
+ msg += "You have been sent the $[pay], as agreed."
+ else
+ msg += "However, we were unable to send you the $[pay] you're entitled."
+ if(useMS && P)
+ useMS.send_pda_message("[P.owner]", "[command_name()] Payroll", msg)
+
+ var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
+ PM.notify("Message from [command_name()] (Payroll), \"[msg]\" (Unable to Reply)", 0)
+ break
+
+/datum/game_mode/proc/check_finished() //to be called by ticker
+ if(shuttle_master.emergency.mode >= SHUTTLE_ENDGAME || station_was_nuked)
+ return 1
+ return 0
+
+/datum/game_mode/proc/cleanup() //This is called when the round has ended but not the game, if any cleanup would be necessary in that case.
+ return
+
+/datum/game_mode/proc/declare_completion()
+ var/clients = 0
+ var/surviving_humans = 0
+ var/surviving_total = 0
+ var/ghosts = 0
+ var/escaped_humans = 0
+ var/escaped_total = 0
+ var/escaped_on_pod_1 = 0
+ var/escaped_on_pod_2 = 0
+ var/escaped_on_pod_3 = 0
+ var/escaped_on_pod_5 = 0
+ var/escaped_on_shuttle = 0
+
+ var/list/area/escape_locations = list(/area/shuttle/escape, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom)
+
+ if(shuttle_master.emergency.mode < SHUTTLE_ENDGAME) //shuttle didn't get to centcom
+ escape_locations -= /area/shuttle/escape
+
+ for(var/mob/M in player_list)
+ if(M.client)
+ clients++
+ if(ishuman(M))
+ if(!M.stat)
+ surviving_humans++
+ if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
+ escaped_humans++
+ if(!M.stat)
+ surviving_total++
+ if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations)
+ escaped_total++
+
+ if(M.loc && M.loc.loc && M.loc.loc.type == shuttle_master.emergency.areaInstance.type && shuttle_master.emergency.mode >= SHUTTLE_ENDGAME)
+ escaped_on_shuttle++
+
+ if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod1/centcom)
+ escaped_on_pod_1++
+ if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod2/centcom)
+ escaped_on_pod_2++
+ if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod3/centcom)
+ escaped_on_pod_3++
+ if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod5/centcom)
+ escaped_on_pod_5++
+
+ if(isobserver(M))
+ ghosts++
+
+ if(clients > 0)
+ feedback_set("round_end_clients",clients)
+ if(ghosts > 0)
+ feedback_set("round_end_ghosts",ghosts)
+ if(surviving_humans > 0)
+ feedback_set("survived_human",surviving_humans)
+ if(surviving_total > 0)
+ feedback_set("survived_total",surviving_total)
+ if(escaped_humans > 0)
+ feedback_set("escaped_human",escaped_humans)
+ if(escaped_total > 0)
+ feedback_set("escaped_total",escaped_total)
+ if(escaped_on_shuttle > 0)
+ feedback_set("escaped_on_shuttle",escaped_on_shuttle)
+ if(escaped_on_pod_1 > 0)
+ feedback_set("escaped_on_pod_1",escaped_on_pod_1)
+ if(escaped_on_pod_2 > 0)
+ feedback_set("escaped_on_pod_2",escaped_on_pod_2)
+ if(escaped_on_pod_3 > 0)
+ feedback_set("escaped_on_pod_3",escaped_on_pod_3)
+ if(escaped_on_pod_5 > 0)
+ feedback_set("escaped_on_pod_5",escaped_on_pod_5)
+
+ send2mainirc("A round of [src.name] has ended - [surviving_total] survivors, [ghosts] ghosts.")
+ return 0
+
+
+/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere.
+ return 0
+
+/datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=0)
+ var/list/players = list()
+ var/list/candidates = list()
+ //var/list/drafted = list()
+ //var/datum/mind/applicant = null
+
+ var/roletext = get_roletext(role)
+
+ // Assemble a list of active players without jobbans.
+ for(var/mob/new_player/player in player_list)
+ if(player.client && player.ready)
+ if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext))
+ if(player_old_enough_antag(player.client,role))
+ players += player
+
+ // Shuffle the players list so that it becomes ping-independent.
+ players = shuffle(players)
+
+ // Get a list of all the people who want to be the antagonist for this round, except those with incompatible species
+ for(var/mob/new_player/player in players)
+ if((role in player.client.prefs.be_special) && !(player.client.prefs.species in protected_species))
+ log_debug("[player.key] had [roletext] enabled, so we are drafting them.")
+ candidates += player.mind
+ players -= player
+
+ // If we don't have enough antags, draft people who voted for the round.
+ if(candidates.len < recommended_enemies)
+ for(var/key in round_voters)
+ for(var/mob/new_player/player in players)
+ if(player.ckey == key)
+ log_debug("[player.key] voted for this round, so we are drafting them.")
+ candidates += player.mind
+ players -= player
+ break
+
+ // Remove candidates who want to be antagonist but have a job that precludes it
+ if(restricted_jobs)
+ for(var/datum/mind/player in candidates)
+ for(var/job in restricted_jobs)
+ if(player.assigned_role == job)
+ candidates -= player
+
+
+ return candidates // Returns: The number of people who had the antagonist role set to yes, regardless of recomended_enemies, if that number is greater than recommended_enemies
+ // recommended_enemies if the number of people with that role set to yes is less than recomended_enemies,
+ // Less if there are not enough valid players in the game entirely to make recommended_enemies.
+
+
+/datum/game_mode/proc/latespawn(var/mob)
+
+/*
+/datum/game_mode/proc/check_player_role_pref(var/role, var/mob/player)
+ if(player.preferences.be_special & role)
+ return 1
+ return 0
+*/
+
+/datum/game_mode/proc/num_players()
+ . = 0
+ for(var/mob/new_player/P in player_list)
+ if(P.client && P.ready)
+ .++
+
+/datum/game_mode/proc/num_players_started()
+ . = 0
+ for(var/mob/living/carbon/human/H in player_list)
+ if(H.client)
+ .++
+
+///////////////////////////////////
+//Keeps track of all living heads//
+///////////////////////////////////
+/datum/game_mode/proc/get_living_heads()
+ . = list()
+ for(var/mob/living/carbon/human/player in mob_list)
+ if(player.stat != DEAD && player.mind && (player.mind.assigned_role in command_positions))
+ . |= player.mind
+
+
+////////////////////////////
+//Keeps track of all heads//
+////////////////////////////
+/datum/game_mode/proc/get_all_heads()
+ . = list()
+ for(var/mob/player in mob_list)
+ if(player.mind && (player.mind.assigned_role in command_positions))
+ . |= player.mind
+
+//////////////////////////////////////////////
+//Keeps track of all living security members//
+//////////////////////////////////////////////
+/datum/game_mode/proc/get_living_sec()
+ . = list()
+ for(var/mob/living/carbon/human/player in mob_list)
+ if(player.stat != DEAD && player.mind && (player.mind.assigned_role in security_positions))
+ . |= player.mind
+
+////////////////////////////////////////
+//Keeps track of all security members//
+////////////////////////////////////////
+/datum/game_mode/proc/get_all_sec()
+ . = list()
+ for(var/mob/living/carbon/human/player in mob_list)
+ if(player.mind && (player.mind.assigned_role in security_positions))
+ . |= player.mind
+
+/datum/game_mode/proc/check_antagonists_topic(href, href_list[])
+ return 0
+
+/datum/game_mode/New()
+ newscaster_announcements = pick(newscaster_standard_feeds)
+
+//////////////////////////
+//Reports player logouts//
+//////////////////////////
+proc/display_roundstart_logout_report()
+ var/msg = "\blue Roundstart logout report\n\n"
+ for(var/mob/living/L in mob_list)
+
+ if(L.ckey)
+ var/found = 0
+ for(var/client/C in clients)
+ if(C.ckey == L.ckey)
+ found = 1
+ break
+ if(!found)
+ msg += "[L.name] ([L.ckey]), the [L.job] (Disconnected)\n"
+
+
+ if(L.ckey && L.client)
+ if(L.client.inactivity >= (ROUNDSTART_LOGOUT_REPORT_TIME / 2)) //Connected, but inactive (alt+tabbed or something)
+ msg += "[L.name] ([L.ckey]), the [L.job] (Connected, Inactive)\n"
+ continue //AFK client
+ if(L.stat)
+ if(L.suiciding) //Suicider
+ msg += "[L.name] ([L.ckey]), the [L.job] (Suicide)\n"
+ job_master.FreeRole(L.job)
+ message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Suicide)\n")
+ continue //Disconnected client
+ if(L.stat == UNCONSCIOUS)
+ msg += "[L.name] ([L.ckey]), the [L.job] (Dying)\n"
+ continue //Unconscious
+ if(L.stat == DEAD)
+ msg += "[L.name] ([L.ckey]), the [L.job] (Dead)\n"
+ continue //Dead
+
+ continue //Happy connected client
+ for(var/mob/dead/observer/D in mob_list)
+ if(D.mind && (D.mind.original == L || D.mind.current == L))
+ if(L.stat == DEAD)
+ if(L.suiciding) //Suicider
+ msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Suicide)\n"
+ continue //Disconnected client
+ else
+ msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Dead)\n"
+ continue //Dead mob, ghost abandoned
+ else
+ if(D.can_reenter_corpse)
+ msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (This shouldn't appear.)\n"
+ continue //Lolwhat
+ else
+ msg += "[L.name] ([ckey(D.mind.key)]), the [L.job] (Ghosted)\n"
+ job_master.FreeRole(L.job)
+ message_admins("[key_name_admin(L)], the [L.job] has been freed due to (Early Round Ghosted While Alive)\n")
+ continue //Ghosted while alive
+
+
+
+ for(var/mob/M in mob_list)
+ if(M.client && M.client.holder)
+ to_chat(M, msg)
+
+
+proc/get_nt_opposed()
+ var/list/dudes = list()
+ for(var/mob/living/carbon/human/man in player_list)
+ if(man.client)
+ if(man.client.prefs.nanotrasen_relation == "Opposed")
+ dudes += man
+ else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50))
+ dudes += man
+ if(dudes.len == 0) return null
+ return pick(dudes)
+
+//Announces objectives/generic antag text.
+/proc/show_generic_antag_text(var/datum/mind/player)
+ if(player.current)
+ to_chat(player.current, "You are an antagonist! Within the rules, \
+ try to act as an opposing force to the crew. Further RP and try to make sure \
+ other players have fun! If you are confused or at a loss, always adminhelp, \
+ and before taking extreme actions, please try to also contact the administration! \
+ Think through your actions and make the roleplay immersive! Please remember all \
+ rules aside from those without explicit exceptions apply to antagonists.")
+
+/proc/show_objectives(var/datum/mind/player)
+ if(!player || !player.current) return
+
+ var/obj_count = 1
+ to_chat(player.current, "\blue Your current objectives:")
+ for(var/datum/objective/objective in player.objectives)
+ to_chat(player.current, "Objective #[obj_count]: [objective.explanation_text]")
+ obj_count++
+
+/proc/get_roletext(var/role)
+ return role
+
+/proc/get_nuke_code()
+ var/nukecode = "ERROR"
+ for(var/obj/machinery/nuclearbomb/bomb in world)
+ if(bomb && bomb.r_code && bomb.z == ZLEVEL_STATION)
+ nukecode = bomb.r_code
+ return nukecode
+
+/datum/game_mode/proc/replace_jobbaned_player(mob/living/M, role_type)
+ var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [role_type]?", role_type, 0, 100)
+ var/mob/dead/observer/theghost = null
+ if(candidates.len)
+ theghost = pick(candidates)
+ to_chat(M, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
+ message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbanned player.")
+ M.ghostize()
+ M.key = theghost.key
+ else
+ message_admins("[M] ([M.key] has been converted into [role_type] with an active antagonist jobban for said role since no ghost has volunteered to take their place.")
+ to_chat(M, "You have been converted into [role_type] with an active jobban. Any further violations of the rules on your part are likely to result in a permanent ban.")
+
+/datum/game_mode/proc/printplayer(datum/mind/ply, fleecheck)
+ var/text = "
[ply.key] was [ply.name] the [ply.assigned_role] and"
+ if(ply.current)
+ if(ply.current.stat == DEAD)
+ text += " died"
+ else
+ text += " survived"
+ if(fleecheck && ply.current.z > ZLEVEL_STATION)
+ text += " while fleeing the station"
+ if(ply.current.real_name != ply.name)
+ text += " as [ply.current.real_name]"
+ else
+ text += " had their body destroyed"
+ return text
+
+/datum/game_mode/proc/printobjectives(datum/mind/ply)
+ var/text = ""
+ var/count = 1
+ for(var/datum/objective/objective in ply.objectives)
+ if(objective.check_completion())
+ text += "
Objective #[count]: [objective.explanation_text] Success!"
+ else
+ text += "
Objective #[count]: [objective.explanation_text] Fail."
+ count++
+ return text
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index f0e2944df04..c894b014a87 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -1,5 +1,5 @@
-/mob/living/simple_animal/hostile/construct
+/mob/living/simple_animal/construct
name = "Construct"
real_name = "Construct"
desc = ""
@@ -19,11 +19,10 @@
faction = list("cult")
flying = 1
universal_speak = 1
- AIStatus = AI_OFF //normal constructs don't have AI
var/list/construct_spells = list()
- var/playstyle_string = "You are a generic construct! Your job is to not exist, and you should probably adminhelp this."
+ loot = list(/obj/item/weapon/reagent_containers/food/snacks/ectoplasm)
-/mob/living/simple_animal/hostile/construct/New()
+/mob/living/simple_animal/construct/New()
..()
name = text("[initial(name)] ([rand(1, 1000)])")
real_name = name
@@ -31,17 +30,16 @@
AddSpell(new spell(src))
updateglow()
-/mob/living/simple_animal/hostile/construct/death()
+/mob/living/simple_animal/construct/death()
..()
- new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc)
for(var/mob/M in viewers(src, null))
if((M.client && !( M.blinded )))
- M.show_message("[src] collapses in a shattered heap.")
+ M.show_message("\red [src] collapses in a shattered heap. ")
ghostize()
qdel(src)
return
-/mob/living/simple_animal/hostile/construct/examine(mob/user)
+/mob/living/simple_animal/construct/examine(mob/user)
..(user)
var/msg = ""
@@ -56,34 +54,32 @@
to_chat(user, msg)
-/mob/living/simple_animal/hostile/construct/attack_animal(mob/living/simple_animal/M)
- if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
- if(health < maxHealth)
- adjustBruteLoss(-5)
- if(src != M)
- Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
- M.visible_message("[M] repairs some of \the [src]'s dents.", \
- "You repair some of [src]'s dents, leaving [src] at [health]/[maxHealth] health.")
- else
- M.visible_message("[M] repairs some of its own dents.", \
- "You repair some of your own dents, leaving you at [M.health]/[M.maxHealth] health.")
+/mob/living/simple_animal/construct/attack_animal(mob/living/simple_animal/M as mob)
+ if(istype(M, /mob/living/simple_animal/construct/builder))
+ health += 5
+ M.custom_emote(1,"mends some of \the [src]'s wounds.")
+ else
+ if(M.melee_damage_upper <= 0)
+ M.custom_emote(1, "[M.friendly] \the [src]")
else
- if(src != M)
- to_chat(M, "You cannot repair [src]'s dents, as it has none!")
- else
- to_chat(M, "You cannot repair your own dents, as you have none!")
- else if(src != M)
- ..()
+ M.do_attack_animation(src)
+ if(M.attack_sound)
+ playsound(loc, M.attack_sound, 50, 1, 1)
+ for(var/mob/O in viewers(src, null))
+ O.show_message("\The [M] [M.attacktext] \the [src]!", 1)
+ add_logs(M, src, "attacked")
+ var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
+ adjustBruteLoss(damage)
-/mob/living/simple_animal/hostile/construct/narsie_act()
+/mob/living/simple_animal/construct/narsie_act()
return
/////////////////Juggernaut///////////////
-/mob/living/simple_animal/hostile/construct/armoured
+/mob/living/simple_animal/construct/armoured
name = "Juggernaut"
real_name = "Juggernaut"
desc = "A possessed suit of armour driven by the will of the restless dead"
@@ -103,19 +99,13 @@
status_flags = 0
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
force_threshold = 11
- playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \
- create shield walls, rip apart enemies and walls alike, and even deflect energy weapons."
-/mob/living/simple_animal/hostile/construct/armoured/hostile //actually hostile, will move around, hit things
- AIStatus = AI_ON
- environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
-
-/mob/living/simple_animal/hostile/construct/armoured/Life()
+/mob/living/simple_animal/construct/armoured/Life()
weakened = 0
return ..()
-/mob/living/simple_animal/hostile/construct/armoured/bullet_act(var/obj/item/projectile/P)
+/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
var/reflectchance = 80 - round(P.damage/3)
if(prob(reflectchance))
@@ -148,7 +138,7 @@
-/mob/living/simple_animal/hostile/construct/wraith
+/mob/living/simple_animal/construct/wraith
name = "Wraith"
real_name = "Wraith"
desc = "A wicked bladed shell contraption piloted by a bound spirit"
@@ -163,17 +153,14 @@
see_in_dark = 7
attack_sound = 'sound/weapons/bladeslice.ogg'
construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
- retreat_distance = 2 //AI wraiths will move in and out of combat
- playstyle_string = "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls."
-/mob/living/simple_animal/hostile/construct/wraith/hostile //actually hostile, will move around, hit things
- AIStatus = AI_ON
+
/////////////////////////////Artificer/////////////////////////
-/mob/living/simple_animal/hostile/construct/builder
+/mob/living/simple_animal/construct/builder
name = "Artificer"
real_name = "Artificer"
desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies"
@@ -188,69 +175,18 @@
melee_damage_upper = 5
attacktext = "rams"
environment_smash = 2
- retreat_distance = 10
- minimum_distance = 10 //AI artificers will flee like fuck
attack_sound = 'sound/weapons/punch2.ogg'
construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser,
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall,
/obj/effect/proc_holder/spell/aoe_turf/conjure/floor,
- /obj/effect/proc_holder/spell/aoe_turf/conjure/pylon,
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone,
/obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser)
- playstyle_string = "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, \
- use magic missile, repair allied constructs (by clicking on them), \
- and, most important of all, create new constructs by producing soulstones to capture souls, \
- and shells to place those soulstones into."
-
-
-/mob/living/simple_animal/hostile/construct/builder/Found(atom/A) //what have we found here?
- if(istype(A, /mob/living/simple_animal/hostile/construct)) //is it a construct?
- var/mob/living/simple_animal/hostile/construct/C = A
- if(C.health < C.maxHealth) //is it hurt? let's go heal it if it is
- return 1
- else
- return 0
- else
- return 0
-
-/mob/living/simple_animal/hostile/construct/builder/CanAttack(atom/the_target)
- if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
- return 0
- if(Found(the_target) || ..()) //If we Found it or Can_Attack it normally, we Can_Attack it as long as it wasn't invisible
- return 1 //as a note this shouldn't be added to base hostile mobs because it'll mess up retaliate hostile mobs
-
-/mob/living/simple_animal/hostile/construct/builder/MoveToTarget(var/list/possible_targets)
- ..()
- if(isliving(target))
- var/mob/living/L = target
- if(istype(L, /mob/living/simple_animal/hostile/construct) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it
- LoseTarget()
- return 0
- if(L.health <= melee_damage_lower+melee_damage_upper) //ey bucko you're hurt as fuck let's go hit you
- retreat_distance = null
- minimum_distance = 1
-
-/mob/living/simple_animal/hostile/construct/builder/Aggro()
- ..()
- if(istype(target, /mob/living/simple_animal/hostile/construct)) //oh the target is a construct no need to flee
- retreat_distance = null
- minimum_distance = 1
-
-/mob/living/simple_animal/hostile/construct/builder/LoseAggro()
- ..()
- retreat_distance = initial(retreat_distance)
- minimum_distance = initial(minimum_distance)
-
-/mob/living/simple_animal/hostile/construct/builder/hostile //actually hostile, will move around, hit things, heal other constructs
- AIStatus = AI_ON
- environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
-
/////////////////////////////Behemoth/////////////////////////
-/mob/living/simple_animal/hostile/construct/behemoth
+/mob/living/simple_animal/construct/behemoth
name = "Behemoth"
real_name = "Behemoth"
desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal."
@@ -272,18 +208,10 @@
var/energy = 0
var/max_energy = 1000
-/mob/living/simple_animal/hostile/construct/behemoth/hostile //actually hostile, will move around, hit things
- AIStatus = AI_ON
- environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
-
-/mob/living/simple_animal/hostile/construct/behemoth/Life()
- weakened = 0
- return ..()
-
/////////////////////////////Harvester/////////////////////////
-/mob/living/simple_animal/hostile/construct/harvester
+/mob/living/simple_animal/construct/harvester
name = "Harvester"
real_name = "Harvester"
desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon."
@@ -297,24 +225,16 @@
attacktext = "prods"
speed = 0
environment_smash = 1
- see_in_dark = 8
+ see_in_dark = 7
attack_sound = 'sound/weapons/tap.ogg'
construct_spells = list(/obj/effect/proc_holder/spell/targeted/smoke/disable)
- retreat_distance = 2 //AI harvesters will move in and out of combat, like wraiths, but shittier
- playstyle_string = "You are a Harvester. You are not strong, but your powers of domination will assist you in your role: \
- Bring those who still cling to this world of illusion back to the master so they may know Truth."
-
-/mob/living/simple_animal/hostile/construct/harvester/Process_Spacemove(var/movement_dir = 0)
+/mob/living/simple_animal/construct/harvester/Process_Spacemove(var/movement_dir = 0)
return 1
-/mob/living/simple_animal/hostile/construct/harvester/hostile //actually hostile, will move around, hit things
- AIStatus = AI_ON
-
-
////////////////Glow////////////////////
-/mob/living/simple_animal/hostile/construct/proc/updateglow()
+/mob/living/simple_animal/construct/proc/updateglow()
overlays = 0
var/overlay_layer = LIGHTING_LAYER + 1
if(layer != MOB_LAYER)
@@ -331,7 +251,7 @@
set category = "Behemoth"
set name = "Summon Cultist (300)"
set desc = "Teleport a cultist to your location"
- if (istype(usr,/mob/living/simple_animal/hostile/constructbehemoth))
+ if (istype(usr,/mob/living/simple_animal/constructbehemoth))
if(usr.energy<300)
to_chat(usr, "\red You do not have enough power stored!")
@@ -352,77 +272,3 @@
return
cultist.loc = usr.loc
usr.visible_message("/red [cultist] appears in a flash of red light as [usr] glows with power")*/
-
-
-///ui stuff
-
-/mob/living/simple_animal/hostile/construct/armoured/handle_hud_icons_health()
- ..()
- if(healths)
- switch(health)
- if(250 to INFINITY) healths.icon_state = "juggernaut_health0"
- if(208 to 249) healths.icon_state = "juggernaut_health1"
- if(167 to 207) healths.icon_state = "juggernaut_health2"
- if(125 to 166) healths.icon_state = "juggernaut_health3"
- if(84 to 124) healths.icon_state = "juggernaut_health4"
- if(42 to 83) healths.icon_state = "juggernaut_health5"
- if(1 to 41) healths.icon_state = "juggernaut_health6"
- else healths.icon_state = "juggernaut_health7"
-
-
-/mob/living/simple_animal/hostile/construct/behemoth/handle_hud_icons_health()
- ..()
- if(healths)
- switch(health)
- if(750 to INFINITY) healths.icon_state = "juggernaut_health0"
- if(625 to 749) healths.icon_state = "juggernaut_health1"
- if(500 to 624) healths.icon_state = "juggernaut_health2"
- if(375 to 499) healths.icon_state = "juggernaut_health3"
- if(250 to 374) healths.icon_state = "juggernaut_health4"
- if(125 to 249) healths.icon_state = "juggernaut_health5"
- if(1 to 124) healths.icon_state = "juggernaut_health6"
- else healths.icon_state = "juggernaut_health7"
-
-/mob/living/simple_animal/hostile/construct/builder/handle_hud_icons_health()
- ..()
- if(healths)
- switch(health)
- if(50 to INFINITY) healths.icon_state = "artificer_health0"
- if(42 to 49) healths.icon_state = "artificer_health1"
- if(34 to 41) healths.icon_state = "artificer_health2"
- if(26 to 33) healths.icon_state = "artificer_health3"
- if(18 to 25) healths.icon_state = "artificer_health4"
- if(10 to 17) healths.icon_state = "artificer_health5"
- if(1 to 9) healths.icon_state = "artificer_health6"
- else healths.icon_state = "artificer_health7"
-
-
-
-/mob/living/simple_animal/hostile/construct/wraith/handle_hud_icons_health()
-
- ..()
- if(healths)
- switch(health)
- if(75 to INFINITY) healths.icon_state = "wraith_health0"
- if(62 to 74) healths.icon_state = "wraith_health1"
- if(50 to 61) healths.icon_state = "wraith_health2"
- if(37 to 49) healths.icon_state = "wraith_health3"
- if(25 to 36) healths.icon_state = "wraith_health4"
- if(12 to 24) healths.icon_state = "wraith_health5"
- if(1 to 11) healths.icon_state = "wraith_health6"
- else healths.icon_state = "wraith_health7"
-
-
-/mob/living/simple_animal/hostile/construct/harvester/handle_hud_icons_health()
-
- ..()
- if(healths)
- switch(health)
- if(150 to INFINITY) healths.icon_state = "harvester_health0"
- if(125 to 149) healths.icon_state = "harvester_health1"
- if(100 to 124) healths.icon_state = "harvester_health2"
- if(75 to 99) healths.icon_state = "harvester_health3"
- if(50 to 74) healths.icon_state = "harvester_health4"
- if(25 to 49) healths.icon_state = "harvester_health5"
- if(1 to 24) healths.icon_state = "harvester_health6"
- else healths.icon_state = "harvester_health7"
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/constructs2.dm b/code/modules/mob/living/simple_animal/constructs2.dm
new file mode 100644
index 00000000000..67aea80b539
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/constructs2.dm
@@ -0,0 +1,428 @@
+
+/mob/living/simple_animal/hostile/construct
+ name = "Construct"
+ real_name = "Construct"
+ desc = ""
+ speak_emote = list("hisses")
+ emote_hear = list("wails","screeches")
+ response_help = "thinks better of touching"
+ response_disarm = "flails at"
+ response_harm = "punches"
+ icon_dead = "shade_dead"
+ speed = 0
+ a_intent = I_HARM
+ stop_automated_movement = 1
+ status_flags = CANPUSH
+ attack_sound = 'sound/weapons/punch1.ogg'
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
+ minbodytemp = 0
+ faction = list("cult")
+ flying = 1
+ universal_speak = 1
+ AIStatus = AI_OFF //normal constructs don't have AI
+ var/list/construct_spells = list()
+ var/playstyle_string = "You are a generic construct! Your job is to not exist, and you should probably adminhelp this."
+
+/mob/living/simple_animal/hostile/construct/New()
+ ..()
+ name = text("[initial(name)] ([rand(1, 1000)])")
+ real_name = name
+ for(var/spell in construct_spells)
+ AddSpell(new spell(src))
+ updateglow()
+
+/mob/living/simple_animal/hostile/construct/death()
+ ..()
+ new /obj/item/weapon/reagent_containers/food/snacks/ectoplasm (src.loc)
+ for(var/mob/M in viewers(src, null))
+ if((M.client && !( M.blinded )))
+ M.show_message("[src] collapses in a shattered heap.")
+ ghostize()
+ qdel(src)
+ return
+
+/mob/living/simple_animal/hostile/construct/examine(mob/user)
+ ..(user)
+
+ var/msg = ""
+ if (src.health < src.maxHealth)
+ msg += ""
+ if (src.health >= src.maxHealth/2)
+ msg += "It looks slightly dented.\n"
+ else
+ msg += "It looks severely dented!\n"
+ msg += ""
+ msg += "*---------*"
+
+ to_chat(user, msg)
+
+/mob/living/simple_animal/hostile/construct/attack_animal(mob/living/simple_animal/M)
+ if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
+ if(health < maxHealth)
+ adjustBruteLoss(-5)
+ if(src != M)
+ Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
+ M.visible_message("[M] repairs some of \the [src]'s dents.", \
+ "You repair some of [src]'s dents, leaving [src] at [health]/[maxHealth] health.")
+ else
+ M.visible_message("[M] repairs some of its own dents.", \
+ "You repair some of your own dents, leaving you at [M.health]/[M.maxHealth] health.")
+ else
+ if(src != M)
+ to_chat(M, "You cannot repair [src]'s dents, as it has none!")
+ else
+ to_chat(M, "You cannot repair your own dents, as you have none!")
+ else if(src != M)
+ ..()
+
+
+/mob/living/simple_animal/hostile/construct/narsie_act()
+ return
+
+/////////////////Juggernaut///////////////
+
+
+
+/mob/living/simple_animal/hostile/construct/armoured
+ name = "Juggernaut"
+ real_name = "Juggernaut"
+ desc = "A possessed suit of armour driven by the will of the restless dead"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "behemoth"
+ icon_living = "behemoth"
+ maxHealth = 250
+ health = 250
+ response_harm = "harmlessly punches"
+ harm_intent_damage = 0
+ melee_damage_lower = 30
+ melee_damage_upper = 30
+ attacktext = "smashes their armoured gauntlet into"
+ speed = 3
+ environment_smash = 2
+ attack_sound = 'sound/weapons/punch3.ogg'
+ status_flags = 0
+ construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall)
+ force_threshold = 11
+ playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \
+ create shield walls, rip apart enemies and walls alike, and even deflect energy weapons."
+
+
+/mob/living/simple_animal/hostile/construct/armoured/hostile //actually hostile, will move around, hit things
+ AIStatus = AI_ON
+ environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
+
+/mob/living/simple_animal/hostile/construct/armoured/Life()
+ weakened = 0
+ return ..()
+
+/mob/living/simple_animal/hostile/construct/armoured/bullet_act(var/obj/item/projectile/P)
+ if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
+ var/reflectchance = 80 - round(P.damage/3)
+ if(prob(reflectchance))
+ if((P.damage_type == BRUTE || P.damage_type == BURN))
+ adjustBruteLoss(P.damage * 0.5)
+ visible_message("The [P.name] gets reflected by [src]'s shell!", \
+ "The [P.name] gets reflected by [src]'s shell!")
+
+ // Find a turf near or on the original location to bounce to
+ if(P.starting)
+ var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
+ var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
+ var/turf/curloc = get_turf(src)
+
+ // redirect the projectile
+ P.original = locate(new_x, new_y, P.z)
+ P.starting = curloc
+ P.current = curloc
+ P.firer = src
+ P.yo = new_y - curloc.y
+ P.xo = new_x - curloc.x
+
+ return -1 // complete projectile permutation
+
+ return (..(P))
+
+
+
+////////////////////////Wraith/////////////////////////////////////////////
+
+
+
+/mob/living/simple_animal/hostile/construct/wraith
+ name = "Wraith"
+ real_name = "Wraith"
+ desc = "A wicked bladed shell contraption piloted by a bound spirit"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "floating"
+ icon_living = "floating"
+ maxHealth = 75
+ health = 75
+ melee_damage_lower = 25
+ melee_damage_upper = 25
+ attacktext = "slashes"
+ see_in_dark = 7
+ attack_sound = 'sound/weapons/bladeslice.ogg'
+ construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift)
+ retreat_distance = 2 //AI wraiths will move in and out of combat
+ playstyle_string = "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls."
+
+/mob/living/simple_animal/hostile/construct/wraith/hostile //actually hostile, will move around, hit things
+ AIStatus = AI_ON
+
+/////////////////////////////Artificer/////////////////////////
+
+
+
+/mob/living/simple_animal/hostile/construct/builder
+ name = "Artificer"
+ real_name = "Artificer"
+ desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies"
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "artificer"
+ icon_living = "artificer"
+ maxHealth = 50
+ health = 50
+ response_harm = "viciously beats"
+ harm_intent_damage = 5
+ melee_damage_lower = 5
+ melee_damage_upper = 5
+ attacktext = "rams"
+ environment_smash = 2
+ retreat_distance = 10
+ minimum_distance = 10 //AI artificers will flee like fuck
+ attack_sound = 'sound/weapons/punch2.ogg'
+ construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser,
+ /obj/effect/proc_holder/spell/aoe_turf/conjure/wall,
+ /obj/effect/proc_holder/spell/aoe_turf/conjure/floor,
+ /obj/effect/proc_holder/spell/aoe_turf/conjure/pylon,
+ /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone,
+ /obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser)
+
+ playstyle_string = "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, \
+ use magic missile, repair allied constructs (by clicking on them), \
+ and, most important of all, create new constructs by producing soulstones to capture souls, \
+ and shells to place those soulstones into."
+
+
+/mob/living/simple_animal/hostile/construct/builder/Found(atom/A) //what have we found here?
+ if(istype(A, /mob/living/simple_animal/hostile/construct)) //is it a construct?
+ var/mob/living/simple_animal/hostile/construct/C = A
+ if(C.health < C.maxHealth) //is it hurt? let's go heal it if it is
+ return 1
+ else
+ return 0
+ else
+ return 0
+
+/mob/living/simple_animal/hostile/construct/builder/CanAttack(atom/the_target)
+ if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
+ return 0
+ if(Found(the_target) || ..()) //If we Found it or Can_Attack it normally, we Can_Attack it as long as it wasn't invisible
+ return 1 //as a note this shouldn't be added to base hostile mobs because it'll mess up retaliate hostile mobs
+
+/mob/living/simple_animal/hostile/construct/builder/MoveToTarget(var/list/possible_targets)
+ ..()
+ if(isliving(target))
+ var/mob/living/L = target
+ if(istype(L, /mob/living/simple_animal/hostile/construct) && L.health >= L.maxHealth) //is this target an unhurt construct? stop trying to heal it
+ LoseTarget()
+ return 0
+ if(L.health <= melee_damage_lower+melee_damage_upper) //ey bucko you're hurt as fuck let's go hit you
+ retreat_distance = null
+ minimum_distance = 1
+
+/mob/living/simple_animal/hostile/construct/builder/Aggro()
+ ..()
+ if(istype(target, /mob/living/simple_animal/hostile/construct)) //oh the target is a construct no need to flee
+ retreat_distance = null
+ minimum_distance = 1
+
+/mob/living/simple_animal/hostile/construct/builder/LoseAggro()
+ ..()
+ retreat_distance = initial(retreat_distance)
+ minimum_distance = initial(minimum_distance)
+
+/mob/living/simple_animal/hostile/construct/builder/hostile //actually hostile, will move around, hit things, heal other constructs
+ AIStatus = AI_ON
+ environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
+
+
+/////////////////////////////Behemoth/////////////////////////
+
+
+/mob/living/simple_animal/hostile/construct/behemoth
+ name = "Behemoth"
+ real_name = "Behemoth"
+ desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal."
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "behemoth"
+ icon_living = "behemoth"
+ maxHealth = 750
+ health = 750
+ speak_emote = list("rumbles")
+ response_harm = "harmlessly punches"
+ harm_intent_damage = 0
+ melee_damage_lower = 50
+ melee_damage_upper = 50
+ attacktext = "brutally crushes"
+ speed = 5
+ environment_smash = 2
+ attack_sound = 'sound/weapons/punch4.ogg'
+ force_threshold = 11
+ var/energy = 0
+ var/max_energy = 1000
+
+/mob/living/simple_animal/hostile/construct/behemoth/hostile //actually hostile, will move around, hit things
+ AIStatus = AI_ON
+ environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
+
+/mob/living/simple_animal/hostile/construct/behemoth/Life()
+ weakened = 0
+ return ..()
+
+
+/////////////////////////////Harvester/////////////////////////
+
+/mob/living/simple_animal/hostile/construct/harvester
+ name = "Harvester"
+ real_name = "Harvester"
+ desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon."
+ icon = 'icons/mob/mob.dmi'
+ icon_state = "harvester"
+ icon_living = "harvester"
+ maxHealth = 60
+ health = 60
+ melee_damage_lower = 1
+ melee_damage_upper = 5
+ attacktext = "prods"
+ speed = 0
+ environment_smash = 1
+ see_in_dark = 8
+ attack_sound = 'sound/weapons/tap.ogg'
+ construct_spells = list(/obj/effect/proc_holder/spell/targeted/smoke/disable)
+ retreat_distance = 2 //AI harvesters will move in and out of combat, like wraiths, but shittier
+ playstyle_string = "You are a Harvester. You are not strong, but your powers of domination will assist you in your role: \
+ Bring those who still cling to this world of illusion back to the master so they may know Truth."
+
+
+/mob/living/simple_animal/hostile/construct/harvester/Process_Spacemove(var/movement_dir = 0)
+ return 1
+
+
+/mob/living/simple_animal/hostile/construct/harvester/hostile //actually hostile, will move around, hit things
+ AIStatus = AI_ON
+
+
+////////////////Glow////////////////////
+/mob/living/simple_animal/hostile/construct/proc/updateglow()
+ overlays = 0
+ var/overlay_layer = LIGHTING_LAYER + 1
+ if(layer != MOB_LAYER)
+ overlay_layer=TURF_LAYER+0.2
+
+ overlays += image(icon,"glow-[icon_state]",overlay_layer)
+ set_light(2, -2, l_color = "#FFFFFF")
+
+////////////////Powers//////////////////
+
+
+/*
+/client/proc/summon_cultist()
+ set category = "Behemoth"
+ set name = "Summon Cultist (300)"
+ set desc = "Teleport a cultist to your location"
+ if (istype(usr,/mob/living/simple_animal/hostile/constructbehemoth))
+
+ if(usr.energy<300)
+ to_chat(usr, "\red You do not have enough power stored!")
+ return
+
+ if(usr.stat)
+ return
+
+ usr.energy -= 300
+ var/list/mob/living/cultists = new
+ for(var/datum/mind/H in ticker.mode.cult)
+ if (istype(H.current,/mob/living))
+ cultists+=H.current
+ var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr)
+ if(!cultist)
+ return
+ if (cultist == usr) //just to be sure.
+ return
+ cultist.loc = usr.loc
+ usr.visible_message("/red [cultist] appears in a flash of red light as [usr] glows with power")*/
+
+
+///ui stuff
+
+/mob/living/simple_animal/hostile/construct/armoured/handle_hud_icons_health()
+ ..()
+ if(healths)
+ switch(health)
+ if(250 to INFINITY) healths.icon_state = "juggernaut_health0"
+ if(208 to 249) healths.icon_state = "juggernaut_health1"
+ if(167 to 207) healths.icon_state = "juggernaut_health2"
+ if(125 to 166) healths.icon_state = "juggernaut_health3"
+ if(84 to 124) healths.icon_state = "juggernaut_health4"
+ if(42 to 83) healths.icon_state = "juggernaut_health5"
+ if(1 to 41) healths.icon_state = "juggernaut_health6"
+ else healths.icon_state = "juggernaut_health7"
+
+
+/mob/living/simple_animal/hostile/construct/behemoth/handle_hud_icons_health()
+ ..()
+ if(healths)
+ switch(health)
+ if(750 to INFINITY) healths.icon_state = "juggernaut_health0"
+ if(625 to 749) healths.icon_state = "juggernaut_health1"
+ if(500 to 624) healths.icon_state = "juggernaut_health2"
+ if(375 to 499) healths.icon_state = "juggernaut_health3"
+ if(250 to 374) healths.icon_state = "juggernaut_health4"
+ if(125 to 249) healths.icon_state = "juggernaut_health5"
+ if(1 to 124) healths.icon_state = "juggernaut_health6"
+ else healths.icon_state = "juggernaut_health7"
+
+/mob/living/simple_animal/hostile/construct/builder/handle_hud_icons_health()
+ ..()
+ if(healths)
+ switch(health)
+ if(50 to INFINITY) healths.icon_state = "artificer_health0"
+ if(42 to 49) healths.icon_state = "artificer_health1"
+ if(34 to 41) healths.icon_state = "artificer_health2"
+ if(26 to 33) healths.icon_state = "artificer_health3"
+ if(18 to 25) healths.icon_state = "artificer_health4"
+ if(10 to 17) healths.icon_state = "artificer_health5"
+ if(1 to 9) healths.icon_state = "artificer_health6"
+ else healths.icon_state = "artificer_health7"
+
+
+
+/mob/living/simple_animal/hostile/construct/wraith/handle_hud_icons_health()
+
+ ..()
+ if(healths)
+ switch(health)
+ if(75 to INFINITY) healths.icon_state = "wraith_health0"
+ if(62 to 74) healths.icon_state = "wraith_health1"
+ if(50 to 61) healths.icon_state = "wraith_health2"
+ if(37 to 49) healths.icon_state = "wraith_health3"
+ if(25 to 36) healths.icon_state = "wraith_health4"
+ if(12 to 24) healths.icon_state = "wraith_health5"
+ if(1 to 11) healths.icon_state = "wraith_health6"
+ else healths.icon_state = "wraith_health7"
+
+
+/mob/living/simple_animal/hostile/construct/harvester/handle_hud_icons_health()
+
+ ..()
+ if(healths)
+ switch(health)
+ if(150 to INFINITY) healths.icon_state = "harvester_health0"
+ if(125 to 149) healths.icon_state = "harvester_health1"
+ if(100 to 124) healths.icon_state = "harvester_health2"
+ if(75 to 99) healths.icon_state = "harvester_health3"
+ if(50 to 74) healths.icon_state = "harvester_health4"
+ if(25 to 49) healths.icon_state = "harvester_health5"
+ if(1 to 24) healths.icon_state = "harvester_health6"
+ else healths.icon_state = "harvester_health7"
\ No newline at end of file
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 412a3606bd8..a22bb625198 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/items2.dmi b/icons/obj/items2.dmi
new file mode 100644
index 00000000000..412a3606bd8
Binary files /dev/null and b/icons/obj/items2.dmi differ