diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index d8d5484ff5..b29d933866 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -2,4 +2,7 @@ #define ANTAG_DATUM_CULT_MASTER /datum/antagonist/cult/master #define ANTAG_DATUM_CLOCKCULT /datum/antagonist/clockcult #define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent -#define ANTAG_DATUM_DEVIL /datum/antagonist/devil \ No newline at end of file +#define ANTAG_DATUM_DEVIL /datum/antagonist/devil +#define ANTAG_DATUM_NINJA /datum/antagonist/ninja +#define ANTAG_DATUM_NINJA_FRIENDLY /datum/antagonist/ninja/friendly +#define ANTAG_DATUM_NINJA_RANDOM /datum/antagonist/ninja/randomAllegiance/ \ No newline at end of file diff --git a/code/controllers/subsystem/dbcore.dm b/code/controllers/subsystem/dbcore.dm index 9c812192d8..ad4691564c 100644 --- a/code/controllers/subsystem/dbcore.dm +++ b/code/controllers/subsystem/dbcore.dm @@ -152,7 +152,7 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table sqlrowlist += "([row.Join(", ")])" sqlrowlist = " [sqlrowlist.Join(",\n ")]" - var/datum/DBQuery/Query = NewQuery("INSERT[ignore_errors][delayed] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]") + var/datum/DBQuery/Query = NewQuery("INSERT[delayed][ignore_errors] INTO [table]\n([columns.Join(", ")])\nVALUES\n[sqlrowlist]\n[duplicate_key]") if (warn) return Query.warn_execute() else diff --git a/code/datums/action.dm b/code/datums/action.dm index 5a397fe3bd..ba3dc04f56 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -358,6 +358,59 @@ active = FALSE ..() +/datum/action/item_action/initialize_ninja_suit + name = "Toggle ninja suit" + +/datum/action/item_action/ninjajaunt + name = "Phase Jaunt (10E)" + desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing." + button_icon_state = "ninja_phase" + +/datum/action/item_action/ninjasmoke + name = "Smoke Bomb" + desc = "Blind your enemies momentarily with a well-placed smoke bomb." + button_icon_state = "smoke" + +/datum/action/item_action/ninjaboost + name = "Adrenaline Boost" + desc = "Inject a secret chemical that will counteract all movement-impairing effect." + button_icon_state = "repulse" + +/datum/action/item_action/ninjapulse + name = "EM Burst (25E)" + desc = "Disable any nearby technology with a electro-magnetic pulse." + button_icon_state = "emp" + +/datum/action/item_action/ninjastar + name = "Create Throwing Stars (1E)" + desc = "Creates some throwing stars" + button_icon_state = "throwingstar" + icon_icon = 'icons/obj/weapons.dmi' + +/datum/action/item_action/ninjanet + name = "Energy Net (20E)" + desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds." + button_icon_state = "energynet" + icon_icon = 'icons/effects/effects.dmi' + +/datum/action/item_action/ninja_sword_recall + name = "Recall Energy Katana (Variable Cost)" + desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance." + button_icon_state = "energy_katana" + icon_icon = 'icons/obj/weapons.dmi' + +/datum/action/item_action/ninja_stealth + name = "Toggle Stealth" + desc = "Toggles stealth mode on and off." + button_icon_state = "ninja_cloak" + +/datum/action/item_action/toggle_glove + name = "Toggle interaction" + desc = "Switch between normal interaction and drain mode." + button_icon_state = "s-ninjan" + icon_icon = 'icons/obj/clothing/gloves.dmi' + + /datum/action/item_action/organ_action check_flags = AB_CHECK_CONSCIOUS diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm new file mode 100644 index 0000000000..d3b6da5b19 --- /dev/null +++ b/code/datums/antagonists/ninja.dm @@ -0,0 +1,153 @@ +/datum/antagonist/ninja + name = "Ninja" + var/team + var/helping_station = 0 + var/give_objectives = TRUE + +/datum/antagonist/ninja/friendly + helping_station = 1 + +/datum/antagonist/ninja/friendly/noobjective + give_objectives = FALSE + +/datum/antagonist/ninja/New(datum/mind/new_owner) + if(new_owner && !ishuman(new_owner.current))//It's fine if we aren't passed a mind, but if we are, they have to be human. + throw EXCEPTION("Only humans and/or humanoids may be ninja'ed") + ..(new_owner) + +/datum/antagonist/ninja/randomAllegiance/New(datum/mind/new_owner) + ..(new_owner) + helping_station = rand(0,1) + +/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current, safety=0)//Safety in case you need to unequip stuff for existing characters. + if(safety) + qdel(H.w_uniform) + qdel(H.wear_suit) + qdel(H.wear_mask) + qdel(H.head) + qdel(H.shoes) + qdel(H.gloves) + + var/obj/item/clothing/suit/space/space_ninja/theSuit = new(H) + var/obj/item/weapon/katana/energy/EK = new(H) + theSuit.energyKatana = EK + + H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_ears) + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/space_ninja(H), slot_shoes) + H.equip_to_slot_or_del(theSuit, slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/space_ninja(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/space_ninja(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/space_ninja(H), slot_wear_mask) + H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night(H), slot_glasses) + H.equip_to_slot_or_del(EK, slot_belt) + H.equip_to_slot_or_del(new /obj/item/device/flashlight(H), slot_r_store) + H.equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(H), slot_l_store) + H.equip_to_slot_or_del(new /obj/item/weapon/tank/internals/emergency_oxygen(H), slot_s_store) + H.equip_to_slot_or_del(new /obj/item/weapon/tank/jetpack/carbondioxide(H), slot_back) + theSuit.randomize_param() + + var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(H) + E.implant(H) + return 1 + +/datum/antagonist/ninja/proc/addMemories() + owner.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!") + owner.store_memory("Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!") + owner.store_memory("Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.") + +/datum/antagonist/ninja/proc/addObjectives(quantity = 6) + var/list/possible_targets = list() + for(var/datum/mind/M in SSticker.minds) + if(M.current && M.current.stat != DEAD) + if(ishuman(M.current)) + if(M.special_role) + possible_targets[M] = 0 //bad-guy + else if(M.assigned_role in GLOB.command_positions) + possible_targets[M] = 1 //good-guy + + var/list/objectives = list(1,2,3,4) + while(owner.objectives.len < quantity) + switch(pick_n_take(objectives)) + if(1) //research + var/datum/objective/download/O = new /datum/objective/download() + O.owner = owner + O.gen_amount_goal() + owner.objectives += O + + if(2) //steal + var/datum/objective/steal/special/O = new /datum/objective/steal/special() + O.owner = owner + owner.objectives += O + + if(3) //protect/kill + if(!possible_targets.len) continue + var/index = rand(1,possible_targets.len) + var/datum/mind/M = possible_targets[index] + var/is_bad_guy = possible_targets[M] + possible_targets.Cut(index,index+1) + + if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy) + var/datum/objective/assassinate/O = new /datum/objective/assassinate() + O.owner = owner + O.target = M + O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." + owner.objectives += O + else //protect + var/datum/objective/protect/O = new /datum/objective/protect() + O.owner = owner + O.target = M + O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." + owner.objectives += O + if(4) //debrain/capture + if(!possible_targets.len) continue + var/selected = rand(1,possible_targets.len) + var/datum/mind/M = possible_targets[selected] + var/is_bad_guy = possible_targets[M] + possible_targets.Cut(selected,selected+1) + + if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy) + var/datum/objective/debrain/O = new /datum/objective/debrain() + O.owner = owner + O.target = M + O.explanation_text = "Steal the brain of [M.current.real_name]." + owner.objectives += O + else //capture + var/datum/objective/capture/O = new /datum/objective/capture() + O.owner = owner + O.gen_amount_goal() + owner.objectives += O + else + break + var/datum/objective/O = new /datum/objective/survive() + O.owner = owner + owner.objectives += O + + +/proc/remove_ninja(mob/living/L) + if(!L || !L.mind) + return FALSE + var/datum/antagonist/datum = L.mind.has_antag_datum(ANTAG_DATUM_NINJA) + datum.on_removal() + return TRUE + +/proc/add_ninja(mob/living/carbon/human/H, type = ANTAG_DATUM_NINJA_RANDOM) + if(!H || !H.mind) + return FALSE + return H.mind.add_antag_datum(type) + +/proc/is_ninja(mob/living/M) + return M && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_NINJA) + + +/datum/antagonist/ninja/greet() + owner.current << sound('sound/effects/ninja_greeting.ogg') + to_chat(owner.current, "I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!") + to_chat(owner.current, "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!") + to_chat(owner.current, "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.") + return + +/datum/antagonist/ninja/on_gain() + if(give_objectives) + addObjectives() + addMemories() diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index fbbf97a6ca..eacbdd4d81 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -737,18 +737,6 @@ src.give_disease(M) href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["ninja"]) - if(!check_rights(R_FUN)) - return - - var/mob/M = locate(href_list["ninja"]) - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.cmd_admin_ninjafy(M) - href_list["datumrefresh"] = href_list["ninja"] - else if(href_list["gib"]) if(!check_rights(R_FUN)) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index dd7a7ba38a..04bec0a7a4 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -326,7 +326,8 @@ "traitor", // "traitorchan", "monkey", "clockcult", - "devil" + "devil", + "ninja" ) var/text = "" @@ -614,9 +615,27 @@ text += "|Disabled in Prefs" sections["devil"] = text +/** NINJA ***/ + text = "ninja" + if(SSticker.mode.config_tag == "ninja") + text = uppertext(text) + text = "[text]: " + var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA) + if(ninjainfo) + if(ninjainfo.helping_station) + text += "employee | syndicate | NANOTRASEN | EQUIP" + else + text += "employee | SYNDICATE | nanotrasen | EQUIP" + else + text += "EMPLOYEE | syndicate | nanotrasen | random allegiance" + if(current && current.client && (ROLE_NINJA in current.client.prefs.be_special)) + text += " | Enabled in Prefs" + else + text += " | Disabled in Prefs" + sections["ninja"] = text - /** SILICON ***/ +/** SILICON ***/ if(issilicon(current)) text = "silicon" var/mob/living/silicon/robot/robot = current @@ -1202,7 +1221,28 @@ else to_chat(usr, "This only works on humans!") return - + else if(href_list["ninja"]) + var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA) + switch(href_list["ninja"]) + if("clear") + remove_ninja(current) + message_admins("[key_name_admin(usr)] has de-ninja'ed [current].") + log_admin("[key_name(usr)] has de-ninja'ed [current].") + if("equip") + ninjainfo.equip_space_ninja() + return + if("nanotrasen") + add_ninja(current, ANTAG_DATUM_NINJA_FRIENDLY) + message_admins("[key_name_admin(usr)] has friendly ninja'ed [current].") + log_admin("[key_name(usr)] has friendly ninja'ed [current].") + if("syndicate") + add_ninja(current, ANTAG_DATUM_NINJA) + message_admins("[key_name_admin(usr)] has syndie ninja'ed [current].") + log_admin("[key_name(usr)] has syndie ninja'ed [current].") + if("random") + add_ninja(current) + message_admins("[key_name_admin(usr)] has random ninja'ed [current].") + log_admin("[key_name(usr)] has random ninja'ed [current].") else if(href_list["abductor"]) switch(href_list["abductor"]) if("clear") @@ -1615,4 +1655,4 @@ /mob/living/silicon/pai/mind_initialize() ..() mind.assigned_role = "pAI" - mind.special_role = "" \ No newline at end of file + mind.special_role = "" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e5f8360527..cdfee917c2 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -81,7 +81,6 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/drop_dynex_bomb, /client/proc/cinematic, /client/proc/one_click_antag, - /client/proc/send_space_ninja, /client/proc/cmd_admin_add_freeform_ai_law, /client/proc/object_say, /client/proc/toggle_random_events, @@ -200,7 +199,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list( /client/proc/get_dynex_power, /client/proc/set_dynex_scale, /client/proc/cinematic, - /client/proc/send_space_ninja, /client/proc/cmd_admin_add_freeform_ai_law, /client/proc/cmd_admin_create_centcom_report, /client/proc/cmd_change_command_name, diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 757721daa3..b82d1f65e2 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -387,9 +387,8 @@ Traitors and the like can also be revived with the previous role mostly intact. for(var/obj/effect/landmark/L in GLOB.landmarks_list) if(L.name=="carpspawn") ninja_spawn += L - new_character.equip_space_ninja() - new_character.internal = new_character.s_store - new_character.update_internals_hud_icon(1) + var/datum/antagonist/ninja/ninjadatum = new_character.mind.has_antag_datum(ANTAG_DATUM_NINJA) + ninjadatum.equip_space_ninja() if(ninja_spawn.len) var/obj/effect/landmark/ninja_spawn_here = pick(ninja_spawn) new_character.loc = ninja_spawn_here.loc diff --git a/code/modules/ninja/admin_ninja_verbs.dm b/code/modules/ninja/admin_ninja_verbs.dm deleted file mode 100644 index 7338d9bb0b..0000000000 --- a/code/modules/ninja/admin_ninja_verbs.dm +++ /dev/null @@ -1,64 +0,0 @@ - -/* - -Contents: -- Admin procs that make ninjas - -*/ - - -//ADMIN CREATE NINJA (From Player) -/client/proc/cmd_admin_ninjafy(mob/living/carbon/human/H in GLOB.player_list) - set category = null - set name = "Make Space Ninja" - - if (!SSticker.mode) - alert("Wait until the game starts") - return - - if(!istype(H)) - return - - if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") - return - - log_admin("[key_name(src)] turned [H.key] into a Space Ninja.") - H.mind = create_ninja_mind(H.key) - H.mind_initialize() - H.equip_space_ninja(1) - if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja)) - H.wear_suit:randomize_param() - spawn(0) - H.wear_suit:ninitialize(10,H) - SSticker.mode.update_ninja_icons_added(H) - - -//ADMIN CREATE NINJA (From Ghost) -/client/proc/send_space_ninja() - set category = "Fun" - set name = "Spawn Space Ninja" - set desc = "Spawns a space ninja for when you need a teenager with attitude." - set popup_menu = 0 - - if(!holder) - to_chat(src, "Only administrators may use this command.") - return - if(!SSticker.mode) - alert("The game hasn't started yet!") - return - if(alert("Are you sure you want to send in a space ninja?",,"Yes","No")=="No") - return - - var/client/C = input("Pick character to spawn as the Space Ninja", "Key", "") as null|anything in GLOB.clients - if(!C) - return - - // passing FALSE means the event doesn't start immediately - var/datum/round_event/ghost_role/ninja/E = new(FALSE) - E.priority_candidates += C - E.processing = TRUE - - message_admins("[key_name_admin(key)] has spawned [key_name_admin(C.key)] as a Space Ninja.") - log_admin("[key] used Spawn Space Ninja.") - - return diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index e83f3a17e2..8ff3652367 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -63,98 +63,21 @@ Contents: Mind.active = 1 //generate objectives - You'll generally get 6 objectives (Ninja is meant to be hardmode!) - var/list/possible_targets = list() - for(var/datum/mind/M in SSticker.minds) - if(M.current && M.current.stat != DEAD) - if(ishuman(M.current)) - if(M.special_role) - possible_targets[M] = 0 //bad-guy - else if(M.assigned_role in GLOB.command_positions) - possible_targets[M] = 1 //good-guy - var/list/objectives = list(1,2,3,4) - while(give_objectives && Mind.objectives.len < 6) - switch(pick_n_take(objectives)) - if(1) //research - var/datum/objective/download/O = new /datum/objective/download() - O.owner = Mind - O.gen_amount_goal() - Mind.objectives += O - - if(2) //steal - var/datum/objective/steal/special/O = new /datum/objective/steal/special() - O.owner = Mind - Mind.objectives += O - - if(3) //protect/kill - if(!possible_targets.len) continue - var/index = rand(1,possible_targets.len) - var/datum/mind/M = possible_targets[index] - var/is_bad_guy = possible_targets[M] - possible_targets.Cut(index,index+1) - - if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/assassinate/O = new /datum/objective/assassinate() - O.owner = Mind - O.target = M - O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." - Mind.objectives += O - else //protect - var/datum/objective/protect/O = new /datum/objective/protect() - O.owner = Mind - O.target = M - O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." - Mind.objectives += O - if(4) //debrain/capture - if(!possible_targets.len) continue - var/selected = rand(1,possible_targets.len) - var/datum/mind/M = possible_targets[selected] - var/is_bad_guy = possible_targets[M] - possible_targets.Cut(selected,selected+1) - - if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/debrain/O = new /datum/objective/debrain() - O.owner = Mind - O.target = M - O.explanation_text = "Steal the brain of [M.current.real_name]." - Mind.objectives += O - else //capture - var/datum/objective/capture/O = new /datum/objective/capture() - O.owner = Mind - O.gen_amount_goal() - Mind.objectives += O - else - break - - //Add a survival objective since it's usually broad enough for any round type. - if(give_objectives) - var/datum/objective/O = new /datum/objective/survive() - O.owner = Mind - Mind.objectives += O - - //add some RP-fluff - Mind.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!") - Mind.store_memory("Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!") - Mind.store_memory("Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.") //spawn the ninja and assign the candidate var/mob/living/carbon/human/Ninja = create_space_ninja(spawn_loc) Mind.transfer_to(Ninja) - - //initialise equipment - if(istype(Ninja.wear_suit,/obj/item/clothing/suit/space/space_ninja)) - //Should be true but we have to check these things. - var/obj/item/clothing/suit/space/space_ninja/N = Ninja.wear_suit - N.randomize_param() + var/datum/antagonist/ninja/ninjadatum = add_ninja(Ninja) + ninjadatum.equip_space_ninja() Ninja.internal = Ninja.s_store Ninja.update_internals_hud_icon(1) if(Ninja.mind != Mind) //something has gone wrong! throw EXCEPTION("Ninja created with incorrect mind") - return - Ninja << sound('sound/effects/ninja_greeting.ogg') //so ninja you probably wouldn't even know if you were made one + SSticker.mode.update_ninja_icons_added(Ninja) spawned_mobs += Ninja message_admins("[key_name_admin(Ninja)] has been made into a ninja by an event.") @@ -171,7 +94,6 @@ Contents: A.real_name = "[pick(GLOB.ninja_titles)] [pick(GLOB.ninja_names)]" A.copy_to(new_ninja) new_ninja.dna.update_dna_identity() - new_ninja.equip_space_ninja() return new_ninja @@ -183,38 +105,6 @@ Contents: return Mind -/mob/living/carbon/human/proc/equip_space_ninja(safety=0)//Safety in case you need to unequip stuff for existing characters. - if(safety) - qdel(w_uniform) - qdel(wear_suit) - qdel(wear_mask) - qdel(head) - qdel(shoes) - qdel(gloves) - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src) - var/obj/item/clothing/suit/space/space_ninja/theSuit = new(src) - var/obj/item/weapon/katana/energy/EK = new(src) - theSuit.energyKatana = EK - - equip_to_slot_or_del(R, slot_ears) - equip_to_slot_or_del(new /obj/item/clothing/under/color/black(src), slot_w_uniform) - equip_to_slot_or_del(new /obj/item/clothing/shoes/space_ninja(src), slot_shoes) - equip_to_slot_or_del(theSuit, slot_wear_suit) - equip_to_slot_or_del(new /obj/item/clothing/gloves/space_ninja(src), slot_gloves) - equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/space_ninja(src), slot_head) - equip_to_slot_or_del(new /obj/item/clothing/mask/gas/space_ninja(src), slot_wear_mask) - equip_to_slot_or_del(new /obj/item/clothing/glasses/night(src), slot_glasses) - equip_to_slot_or_del(EK, slot_belt) - equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_r_store) - equip_to_slot_or_del(new /obj/item/weapon/grenade/plastic/x4(src), slot_l_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/internals/emergency_oxygen(src), slot_s_store) - equip_to_slot_or_del(new /obj/item/weapon/tank/jetpack/carbondioxide(src), slot_back) - - var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(src) - E.implant(src) - return 1 - /datum/game_mode/proc/update_ninja_icons_added(var/mob/living/carbon/human/ninja) var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA] ninjahud.join_hud(ninja) diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm index d26e4cbd36..e9a350eae3 100644 --- a/code/modules/ninja/suit/gloves.dm +++ b/code/modules/ninja/suit/gloves.dm @@ -58,30 +58,23 @@ A.add_fingerprint(H) draining = 1 - var/drained = A.ninjadrain_act(suit,H,src) + . = A.ninjadrain_act(suit,H,src) draining = 0 - if(isnum(drained)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking) - if(drained) - to_chat(H, "Gained [drained] energy from \the [A].") + if(isnum(.)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking) + if(.) + to_chat(H, "Gained [.] energy from \the [A].") else to_chat(H, "\The [A] has run dry of power, you must find another source!") else - drained = 0 //as to not cancel attack_hand() - - return drained + . = 0 //as to not cancel attack_hand() -/obj/item/clothing/gloves/space_ninja/proc/toggled() - set name = "Toggle Interaction" - set desc = "Toggles special interaction on or off." - set category = "Ninja Equip" - +/obj/item/clothing/gloves/space_ninja/proc/toggledrain() var/mob/living/carbon/human/U = loc to_chat(U, "You [candrain?"disable":"enable"] special interaction.") candrain=!candrain - /obj/item/clothing/gloves/space_ninja/examine(mob/user) ..() if(flags & NODROP) diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm index 30085fdac5..e1c378f9f3 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_adrenaline.dm @@ -1,12 +1,6 @@ - - //Wakes the user so they are able to do their thing. Also injects a decent dose of radium. //Movement impairing would indicate drugs and the like. /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost() - set name = "Adrenaline Boost" - set desc = "Inject a secret chemical that will counteract all movement-impairing effect." - set category = "Ninja Ability" - set popup_menu = 0 if(!ninjacost(0,N_ADRENALINE))//Have to make sure stat is not counted for this ability. var/mob/living/carbon/human/H = affecting @@ -25,4 +19,3 @@ a_boost-- to_chat(H, "There are [a_boost] adrenaline boosts remaining.") s_coold = 3 - return \ No newline at end of file diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_cost_check.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_cost_check.dm index 977279082e..1d728084b3 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_cost_check.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_cost_check.dm @@ -26,4 +26,4 @@ if(!a_boost) to_chat(H, "You do not have any more adrenaline boosters.") return 1 - return (s_coold)//Returns the value of the variable which counts down to zero. \ No newline at end of file + return (s_coold)//Returns the value of the variable which counts down to zero. diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm index 8cfc6b8937..48e3cf69a9 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_empulse.dm @@ -2,14 +2,9 @@ //Disables nearby tech equipment. /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse() - set name = "EM Burst (25E)" - set desc = "Disable any nearby technology with a electro-magnetic pulse." - set category = "Ninja Ability" - set popup_menu = 0 if(!ninjacost(250,N_STEALTH_CANCEL)) var/mob/living/carbon/human/H = affecting playsound(H.loc, 'sound/effects/EMPulse.ogg', 60, 2) empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch. s_coold = 2 - return \ No newline at end of file diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm index 481c4d46b5..18682e87eb 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_net.dm @@ -1,10 +1,6 @@ //Allows the ninja to kidnap people /obj/item/clothing/suit/space/space_ninja/proc/ninjanet(mob/living/carbon/C in oview())//Only living carbon mobs. - set name = "Energy Net (20E)" - set desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds." - set category = null - set src = usr.contents if(!ninjacost(200,N_STEALTH_CANCEL) && iscarbon(C)) var/mob/living/carbon/human/H = affecting @@ -26,4 +22,3 @@ to_chat(H, "[C.p_they(TRUE)] are already trapped inside an energy net!") else to_chat(H, "[C.p_they(TRUE)] will bring no honor to your Clan!") - return \ No newline at end of file diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_smoke.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_smoke.dm index 3596976e9b..3c19162048 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_smoke.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_smoke.dm @@ -2,10 +2,6 @@ //Smoke bomb /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke() - set name = "Smoke Bomb" - set desc = "Blind your enemies momentarily with a well-placed smoke bomb." - set category = "Ninja Ability" - set popup_menu = 0//Will not see it when right clicking. if(!ninjacost(0,N_SMOKE_BOMB)) var/mob/living/carbon/human/H = affecting @@ -16,4 +12,3 @@ s_bombs-- to_chat(H, "There are [s_bombs] smoke bombs remaining.") s_coold = 1 - return \ No newline at end of file diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm index bed0eafd59..336b061a6f 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm @@ -2,11 +2,6 @@ //Creates a throwing star /obj/item/clothing/suit/space/space_ninja/proc/ninjastar() - set name = "Create Throwing Stars (1E)" - set desc = "Creates some throwing stars" - set category = "Ninja Ability" - set popup_menu = 0 - if(!ninjacost(10)) var/mob/living/carbon/human/H = affecting var/obj/item/weapon/throwing_star/ninja/N = new(H) diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm index 12e80d5c09..8103fa2415 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stealth.dm @@ -21,7 +21,6 @@ Contents: animate(U, alpha = 50,time = 15) U.visible_message("[U.name] vanishes into thin air!", \ "You are now mostly invisible to normal detection.") - return /obj/item/clothing/suit/space/space_ninja/proc/cancel_stealth() @@ -38,12 +37,7 @@ Contents: /obj/item/clothing/suit/space/space_ninja/proc/stealth() - set name = "Toggle Stealth" - set desc = "Utilize the internal CLOAK-tech device to activate or deactivate stealth-camo." - set category = "Ninja Equip" - if(!s_busy) toggle_stealth() else to_chat(affecting, "Stealth does not appear to work!") - diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm index 4183e83fbf..73c7082eec 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm @@ -1,10 +1,5 @@ /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall() - set name = "Recall Energy Katana (Variable Cost)" - set desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance." - set category = "Ninja Ability" - set popup_menu = 0 - var/mob/living/carbon/human/H = affecting var/cost = 0 @@ -42,4 +37,3 @@ else //Else just TP it to us. energyKatana.returnToOwner(H,1) - diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm index 2719708675..74dcec12ce 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_teleporting.dm @@ -16,16 +16,10 @@ Contents: var/mob/living/victim = H.pulling if(!victim.anchored) victim.forceMove(locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z)) - return //Jaunt /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt() - set name = "Phase Jaunt (10E)" - set desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing." - set category = "Ninja Ability" - set popup_menu = 0 - if(!ninjacost(100,N_STEALTH_CANCEL)) var/mob/living/carbon/human/H = affecting var/turf/destination = get_teleport_loc(H.loc,H,9,1,3,1,0,1) @@ -47,7 +41,6 @@ Contents: s_coold = 1 else to_chat(H, "The VOID-shift device is malfunctioning, teleportation failed.") - return //Right-Click teleport: It's basically admin "jump to turf" @@ -76,6 +69,3 @@ Contents: s_coold = 1 else to_chat(H, "You cannot teleport into solid walls or from solid matter") - return - - diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm index 827047c93e..d5811e32c9 100644 --- a/code/modules/ninja/suit/suit.dm +++ b/code/modules/ninja/suit/suit.dm @@ -22,6 +22,8 @@ Contents: armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30, fire = 100, acid = 100) strip_delay = 12 + actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjajaunt, /datum/action/item_action/ninjasmoke, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninjanet, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth, /datum/action/item_action/toggle_glove) + //Important parts of the suit. var/mob/living/carbon/human/affecting = null var/obj/item/weapon/stock_parts/cell/cell @@ -57,7 +59,6 @@ Contents: /obj/item/clothing/suit/space/space_ninja/New() ..() - verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb //Spark Init spark_system = new() @@ -109,40 +110,38 @@ Contents: //This proc prevents the suit from being taken off. -/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H, checkIcons = 0) +/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H) if(!istype(H)) return 0 - if(checkIcons) - icon_state = H.gender==FEMALE ? "s-ninjanf" : "s-ninjan" - H.gloves.icon_state = "s-ninjan" - H.gloves.item_state = "s-ninjan" - else - if(H.mind.special_role!="Space Ninja") - to_chat(H, "\red fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR...") - H.gib() - return 0 - if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja)) - to_chat(H, "ERROR: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...") - return 0 - if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja)) - to_chat(H, "ERROR: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...") - return 0 - if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja)) - to_chat(H, "ERROR: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...") - return 0 + if(!is_ninja(H)) + to_chat(H, "\red fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR...") + H.gib() + return FALSE + if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja)) + to_chat(H, "ERROR: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...") + return FALSE + if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja)) + to_chat(H, "ERROR: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...") + return FALSE + if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja)) + to_chat(H, "ERROR: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...") + return FALSE + affecting = H + flags |= NODROP //colons make me go all |= + slowdown = FALSE + n_hood = H.head + n_hood.flags |= NODROP + n_shoes = H.shoes + n_shoes.flags |= NODROP + n_shoes.slowdown-- + n_gloves = H.gloves + n_gloves.flags |= NODROP + return TRUE - affecting = H - flags |= NODROP //colons make me go all |= - slowdown = 0 - n_hood = H.head - n_hood.flags |= NODROP - n_shoes = H.shoes - n_shoes.flags |= NODROP - n_shoes.slowdown-- - n_gloves = H.gloves - n_gloves.flags |= NODROP - - return 1 +/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/H) + icon_state = H.gender==FEMALE ? "s-ninjanf" : "s-ninjan" + H.gloves.icon_state = "s-ninjan" + H.gloves.item_state = "s-ninjan" //This proc allows the suit to be taken off. @@ -172,3 +171,39 @@ Contents: to_chat(user, "The CLOAK-tech device is [s_active?"active":"inactive"].") to_chat(user, "There are [s_bombs] smoke bomb\s remaining.") to_chat(user, "There are [a_boost] adrenaline booster\s remaining.") + +/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action) + if(istype(action, /datum/action/item_action/initialize_ninja_suit)) + toggle_on_off() + return TRUE + if(!s_initialized) + to_chat(user, "ERROR: suit offline. Please activate suit.") + return FALSE + if(istype(action, /datum/action/item_action/ninjajaunt)) + ninjajaunt() + return TRUE + if(istype(action, /datum/action/item_action/ninjasmoke)) + ninjasmoke() + return TRUE + if(istype(action, /datum/action/item_action/ninjaboost)) + ninjaboost() + return TRUE + if(istype(action, /datum/action/item_action/ninjapulse)) + ninjapulse() + return TRUE + if(istype(action, /datum/action/item_action/ninjastar)) + ninjastar() + return TRUE + if(istype(action, /datum/action/item_action/ninjanet)) + ninjanet() + return TRUE + if(istype(action, /datum/action/item_action/ninja_sword_recall)) + ninja_sword_recall() + return TRUE + if(istype(action, /datum/action/item_action/ninja_stealth)) + stealth() + return TRUE + if(istype(action, /datum/action/item_action/toggle_glove)) + n_gloves.toggledrain() + return TRUE + return FALSE diff --git a/code/modules/ninja/suit/suit_initialisation.dm b/code/modules/ninja/suit/suit_initialisation.dm index 6851eb9b48..f26912df24 100644 --- a/code/modules/ninja/suit/suit_initialisation.dm +++ b/code/modules/ninja/suit/suit_initialisation.dm @@ -1,102 +1,98 @@ - -//Verbs link to procs because verb-like procs have a bug which prevents their use if the arguments are not readily referenced. -//^ Old coder words may be false these days, Not taking the risk for now. - -/obj/item/clothing/suit/space/space_ninja/proc/init() - set name = "Initialize Suit" - set desc = "Initializes the suit for field operation." - set category = "Ninja Equip" - - ninitialize() - -/obj/item/clothing/suit/space/space_ninja/proc/deinit() - set name = "De-Initialize Suit" - set desc = "Begins procedure to remove the suit." - set category = "Ninja Equip" - - if(!s_busy) +/obj/item/clothing/suit/space/space_ninja/proc/toggle_on_off() + if(s_busy) + to_chat(loc, "ERROR: You cannot use this function at this time.") + return FALSE + if(s_initialized) deinitialize() else - to_chat(affecting, "The function did not trigger!") - + ninitialize() + . = TRUE /obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/U = loc) - if(U.mind && U.mind.assigned_role==U.mind.special_role && !s_initialized && !s_busy)//Shouldn't be busy... but anything is possible I guess. - s_busy = 1 - for(var/i,i<7,i++) - switch(i) - if(0) - to_chat(U, "Now initializing...") - if(1) - if(!lock_suit(U))//To lock the suit onto wearer. - break - to_chat(U, "Securing external locking mechanism...\nNeural-net established.") - if(2) - to_chat(U, "Extending neural-net interface...\nNow monitoring brain wave pattern...") - if(3) - if(U.stat==2||U.health<=0) - to_chat(U, "FĆAL �Rr�R: 344--93#�&&21 BR��N |/|/aV� PATT$RN RED\nA-A-aB�rT�NG...") - unlock_suit() - break - lock_suit(U,1)//Check for icons. - U.regenerate_icons() - to_chat(U, "Linking neural-net interface...\nPattern\green GREEN, continuing operation.") - if(4) - to_chat(U, "VOID-shift device status: ONLINE.\nCLOAK-tech device status: ONLINE.") - if(5) - to_chat(U, "Primary system status: ONLINE.\nBackup system status: ONLINE.\nCurrent energy capacity: [cell.charge].") - if(6) - to_chat(U, "All systems operational. Welcome to SpiderOS, [U.real_name].") - grant_ninja_verbs() - grant_equip_verbs() - ntick() - sleep(delay) - s_busy = 0 - else - if(!U.mind||U.mind.assigned_role!=U.mind.special_role)//Your run of the mill persons shouldn't know what it is. Or how to turn it on. - to_chat(U, "You do not understand how this suit functions. Where the heck did it even come from?") - else if(s_initialized) - to_chat(U, "The suit is already functioning. Please report this bug.") - else - to_chat(U, "ERROR: You cannot use this function at this time.") - return + if(!U.mind) + return //Not sure how this could happen. + if(!is_ninja(U)) + to_chat(U, "You do not understand how this suit functions. Where the heck did it even come from?") + return + s_busy = TRUE + to_chat(U, "Now initializing...") + addtimer(CALLBACK(src, .proc/ninitialize_two, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_two(delay, mob/living/carbon/human/U) + if(!lock_suit(U))//To lock the suit onto wearer. + s_busy = FALSE + return + to_chat(U, "Securing external locking mechanism...\nNeural-net established.") + addtimer(CALLBACK(src, .proc/ninitialize_three, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_three(delay, mob/living/carbon/human/U) + to_chat(U, "Extending neural-net interface...\nNow monitoring brain wave pattern...") + addtimer(CALLBACK(src, .proc/ninitialize_four, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_four(delay, mob/living/carbon/human/U) + if(U.stat==2||U.health<=0) + to_chat(U, "FĆAL �Rr�R: 344--93#�&&21 BR��N |/|/aV� PATT$RN RED\nA-A-aB�rT�NG...") + unlock_suit() + return + lockIcons(U)//Check for icons. + U.regenerate_icons() + to_chat(U, "Linking neural-net interface...\nPattern\green GREEN, continuing operation.") + addtimer(CALLBACK(src, .proc/ninitialize_five, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_five(delay, mob/living/carbon/human/U) + to_chat(U, "VOID-shift device status: ONLINE.\nCLOAK-tech device status: ONLINE.") + addtimer(CALLBACK(src, .proc/ninitialize_six, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_six(delay, mob/living/carbon/human/U) + to_chat(U, "Primary system status: ONLINE.\nBackup system status: ONLINE.\nCurrent energy capacity: [cell.charge].") + addtimer(CALLBACK(src, .proc/ninitialize_seven, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_seven(delay, mob/living/carbon/human/U) + to_chat(U, "All systems operational. Welcome to SpiderOS, [U.real_name].") + grant_ninja_verbs() + grant_equip_verbs() + ntick() + s_busy = FALSE /obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay) - if(affecting==loc&&!s_busy) + if(affecting==loc) var/mob/living/carbon/human/U = affecting - if(!s_initialized) - to_chat(U, "The suit is not initialized. Please report this bug.") - return if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No") return - if(s_busy) - to_chat(U, "ERROR: You cannot use this function at this time.") - return - s_busy = 1 - for(var/i = 0,i<7,i++) - switch(i) - if(0) - to_chat(U, "Now de-initializing...") - spideros = 0//Spideros resets. - if(1) - to_chat(U, "Logging off, [U:real_name]. Shutting down SpiderOS.") - remove_ninja_verbs() - if(2) - to_chat(U, "Primary system status: OFFLINE.\nBackup system status: OFFLINE.") - if(3) - to_chat(U, "VOID-shift device status: OFFLINE.\nCLOAK-tech device status: OFFLINE.") - cancel_stealth()//Shutdowns stealth. - if(4) - to_chat(U, "Disconnecting neural-net interface...\greenSuccess.") - if(5) - to_chat(U, "Disengaging neural-net interface...\greenSuccess.") - if(6) - to_chat(U, "Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED.") - remove_equip_verbs() - unlock_suit() - U.regenerate_icons() - sleep(delay) - s_busy = 0 - return \ No newline at end of file + s_busy = TRUE + addtimer(CALLBACK(src, .proc/deinitialize_two, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_two(delay, mob/living/carbon/human/U) + to_chat(U, "Now de-initializing...") + spideros = 0//Spideros resets. + addtimer(CALLBACK(src, .proc/deinitialize_three, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_three(delay, mob/living/carbon/human/U) + to_chat(U, "Logging off, [U:real_name]. Shutting down SpiderOS.") + remove_ninja_verbs() + addtimer(CALLBACK(src, .proc/deinitialize_four, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_four(delay, mob/living/carbon/human/U) + to_chat(U, "Primary system status: OFFLINE.\nBackup system status: OFFLINE.") + addtimer(CALLBACK(src, .proc/deinitialize_five, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_five(delay, mob/living/carbon/human/U) + to_chat(U, "VOID-shift device status: OFFLINE.\nCLOAK-tech device status: OFFLINE.") + cancel_stealth()//Shutdowns stealth. + addtimer(CALLBACK(src, .proc/deinitialize_six, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_six(delay, mob/living/carbon/human/U) + to_chat(U, "Disconnecting neural-net interface...\greenSuccess.") + addtimer(CALLBACK(src, .proc/deinitialize_seven, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_seven(delay, mob/living/carbon/human/U) + to_chat(U, "Disengaging neural-net interface...\greenSuccess.") + addtimer(CALLBACK(src, .proc/deinitialize_eight, delay, U), delay) + +/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_eight(delay, mob/living/carbon/human/U) + to_chat(U, "Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED.") + remove_equip_verbs() + U.regenerate_icons() + s_busy = FALSE diff --git a/code/modules/ninja/suit/suit_process.dm b/code/modules/ninja/suit/suit_process.dm index 4b341c9198..99f801ed76 100644 --- a/code/modules/ninja/suit/suit_process.dm +++ b/code/modules/ninja/suit/suit_process.dm @@ -20,5 +20,3 @@ cancel_stealth() sleep(10)//Checks every second. - - diff --git a/code/modules/ninja/suit/suit_verbs_handlers.dm b/code/modules/ninja/suit/suit_verbs_handlers.dm index 24797a272b..7c887da1d2 100644 --- a/code/modules/ninja/suit/suit_verbs_handlers.dm +++ b/code/modules/ninja/suit/suit_verbs_handlers.dm @@ -9,33 +9,20 @@ Contents: */ /obj/item/clothing/suit/space/space_ninja/proc/grant_equip_verbs() - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/init - verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit - verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth - n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled + n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggledrain s_initialized = 1 /obj/item/clothing/suit/space/space_ninja/proc/remove_equip_verbs() - verbs += /obj/item/clothing/suit/space/space_ninja/proc/init - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth if(n_gloves) - n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled + n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggledrain s_initialized = 0 /obj/item/clothing/suit/space/space_ninja/proc/grant_ninja_verbs() verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjastar - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjanet - verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall s_initialized=1 slowdown=0 @@ -43,10 +30,3 @@ Contents: /obj/item/clothing/suit/space/space_ninja/proc/remove_ninja_verbs() verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjashift - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjaboost - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjastar - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjanet - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall diff --git a/code/world.dm b/code/world.dm index 39d34dfd53..b8fbd4eddf 100644 --- a/code/world.dm +++ b/code/world.dm @@ -32,7 +32,7 @@ if(config.sql_enabled) if(SSdbcore.Connect()) log_world("Database connection established.") - var/datum/DBQuery/query_feedback_create_round = SSdbcore.NewQuery("INSERT INTO [format_table_name("feedback")] SELECT null, Now(), MAX(round_id)+1, \"server_ip\", 0, \"[world.internet_address]:[world.port]\" FROM [format_table_name("feedback")]") + var/datum/DBQuery/query_feedback_create_round = SSdbcore.NewQuery("INSERT INTO [format_table_name("feedback")] SELECT null, Now(), IFNULL(MAX(round_id),0)+1, \"server_ip\", 0, \"[world.internet_address]:[world.port]\" FROM [format_table_name("feedback")]") query_feedback_create_round.Execute() var/datum/DBQuery/query_feedback_max_id = SSdbcore.NewQuery("SELECT MAX(round_id) FROM [format_table_name("feedback")]") query_feedback_max_id.Execute() diff --git a/html/changelogs/AutoChangeLog-pr-1037.yml b/html/changelogs/AutoChangeLog-pr-1037.yml new file mode 100644 index 0000000000..ac36de1da2 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1037.yml @@ -0,0 +1,4 @@ +author: "Lordpidey" +delete-after: True +changes: + - tweak: "Space ninjas now use action buttons instead of verbs for a more consistent user experience." diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index 36bf21cf76..7f6f85b004 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/tgstation.dme b/tgstation.dme index b9f0293318..ad998e8286 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -266,6 +266,7 @@ #include "code\datums\antagonists\antag_datum.dm" #include "code\datums\antagonists\datum_clockcult.dm" #include "code\datums\antagonists\datum_cult.dm" +#include "code\datums\antagonists\ninja.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" #include "code\datums\diseases\anxiety.dm" @@ -712,10 +713,10 @@ #include "code\game\objects\effects\decals\decal.dm" #include "code\game\objects\effects\decals\misc.dm" #include "code\game\objects\effects\decals\remains.dm" -#include "code\game\objects\effects\decals\Cleanable\aliens.dm" -#include "code\game\objects\effects\decals\Cleanable\humans.dm" -#include "code\game\objects\effects\decals\Cleanable\misc.dm" -#include "code\game\objects\effects\decals\Cleanable\robots.dm" +#include "code\game\objects\effects\decals\cleanable\aliens.dm" +#include "code\game\objects\effects\decals\cleanable\humans.dm" +#include "code\game\objects\effects\decals\cleanable\misc.dm" +#include "code\game\objects\effects\decals\cleanable\robots.dm" #include "code\game\objects\effects\effect_system\effect_system.dm" #include "code\game\objects\effects\effect_system\effects_explosion.dm" #include "code\game\objects\effects\effect_system\effects_foam.dm" @@ -1816,7 +1817,6 @@ #include "code\modules\modular_computers\NTNet\NTNet_relay.dm" #include "code\modules\modular_computers\NTNet\NTNRC\conversation.dm" #include "code\modules\ninja\__ninjaDefines.dm" -#include "code\modules\ninja\admin_ninja_verbs.dm" #include "code\modules\ninja\energy_katana.dm" #include "code\modules\ninja\ninja_event.dm" #include "code\modules\ninja\Ninja_Readme.dm" diff --git a/tools/tgstation-server/Fix Errors.bat b/tools/tgstation-server/Fix Errors.bat new file mode 100644 index 0000000000..bbe540c82c --- /dev/null +++ b/tools/tgstation-server/Fix Errors.bat @@ -0,0 +1,24 @@ +@echo off +title Automated Error Fixer. +echo This will reset some things, the byond server (DreamDaemon) and the start server script must not be running. Some error messages are normal. +echo You will be prompted to press any key 3 times +pause +pause +pause +cls +echo Resetting folders +mkdir gamecode\a +mkdir gamecode\b +del /S /F /Q gamefolder >nul 2>nul +rmdir /S /q gamefolder +mklink /d gamefolder gamecode\a +call bin\findab.bat +cls +echo Re-Initializing code +call bin\copyfromgit.bat +cls +echo Recompiling the game. If you plan to update or testmerge you can just close this program now and continue. +call bin\build.bat +cls +echo Done! (hopefully) +pause \ No newline at end of file diff --git a/tools/tgstation-server/Merge pr without updating.bat b/tools/tgstation-server/Merge pr without updating.bat new file mode 100644 index 0000000000..da4e023477 --- /dev/null +++ b/tools/tgstation-server/Merge pr without updating.bat @@ -0,0 +1,112 @@ +@echo off +@title Server Updater +SETLOCAL ENABLEDELAYEDEXPANSION +set HOME = %USERPROFILE% + +call config.bat +rem if the first arg to nudge.py is not a channel, it is treated as the "source" +if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" +call bin\getcurdate.bat +call bin\findgit.bat +echo This will handle merging a pr locally, compiling the server, and applying the PR test job. + +:PROMPT +SET /P UserInput=Please enter the pr number (without a # or anything of the sorts): +SET /A PR=UserInput + +if %PR% EQU %UserInput% ( + if %PR% GTR 0 ( + echo updating to pr %PR% + ) else ( + echo Bad input + goto PROMPT + ) +) else ( + echo Bad input + goto PROMPT +) +if exist updating.lk ( + echo ERROR: A current update script has been detected running. if you know this is a mistake: + pause + echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: + pause +) + +echo lock>updating.lk + +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "PR test job started. Merging PR #%PR% locally" >nul 2>nul + + +cd gitrepo +git fetch origin pull/%PR%/head:pr-%PR% +if %ERRORLEVEL% neq 0 ( + cd .. + echo git fetch failed. Aborting test merge. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Git fetch failed. Aborting test merge" + del updating.lk >nul 2>nul + pause + exit /b 1 +) +git merge pr-%PR% +if %ERRORLEVEL% neq 0 ( + cd .. + echo git merge of PR #%PR% failed. Aborting test merge + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "git merge of PR #%PR% failed. Aborting PR test merge" >nul 2>nul + cd gitrepo + git merge --abort + if !ERRORLEVEL! neq 0 ( + echo ERROR: Error aborting test merge, resetting repo. + cd .. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Error aborting test merge, resetting git repo to head" >nul 2>nul + cd gitrepo + git reset --hard + git clean -fd + bin/activepr.bat + del /F /Q prtestjob.lk >nul 2>nul + echo NOTICE: We had to reset the repo's state, all other active test merges were undone. + ) + cd .. + del updating.lk >nul 2>nul + pause + exit /b 1 +) +cd .. + +echo %PR%>>prtestjob.lk +> bin/activepr.bat + +echo ################################## +echo ################################## +echo: +echo Test merging pr done, compiling in 10 seconds. If you want to preform other actions (like more test merges) You can close this now and do them. +echo: +del updating.lk >nul 2>nul + +timeout 10 + +echo lock>updating.lk +call bin\findab.bat + +call bin\copyfromgit.bat + +echo compiling change log +cd gamecode\%AB% +call python tools\ss13_genchangelog.py html/changelog.html html/changelogs +cd ..\.. + +echo Compiling game. +call bin\build.bat +if %DM_EXIT% neq 0 ( + echo DM compile failed. Aborting. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed. Aborting test merge." >nul 2>nul + del /F /Q updating.lk >nul 2>nul + pause + exit /b 1 +) + +del updating.lk >nul 2>nul +rmdir /q gamefolder +mklink /d gamefolder gamecode\%AB% >nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Test merge job finished. Test merge will take place next round." >nul 2>nul +echo Done. The test merge will automatically take place at round restart. +timeout 300 \ No newline at end of file diff --git a/tools/tgstation-server/OnServerBoot.bat b/tools/tgstation-server/OnServerBoot.bat new file mode 100644 index 0000000000..db1f5cc230 --- /dev/null +++ b/tools/tgstation-server/OnServerBoot.bat @@ -0,0 +1,47 @@ +@echo off +title Server Boot Detected. +echo This script is only meant to start byond when the server first boots, do not manually run this. +echo If you manually ran this, close this window NOW. +timeout 15 +start cmd /c "Start Bot.bat" +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +mkdir gamecode\a +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +mkdir gamecode\b +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +del /S /F /Q gamefolder >nul 2>nul +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +rmdir /S /q gamefolder +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +mklink /d gamefolder gamecode\a +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Prepping code +call bin\findab.bat +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Re-Initializing code +call bin\copyfromgit.bat +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Re-Initializing code +cls +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Compiling the game. If you plan to update or testmerge you can just close this program now and continue. +call bin\build.bat +cls +echo Server boot detected. Starting byond and Space Station 13. +echo Starting server and bot. +start cmd /c "Start Server.bat" +timeout 10 \ No newline at end of file diff --git a/tools/tgstation-server/README.md b/tools/tgstation-server/README.md new file mode 100644 index 0000000000..10831fd461 --- /dev/null +++ b/tools/tgstation-server/README.md @@ -0,0 +1,111 @@ +# Tgstation Toolkit: +This is a toolset to manage a production server of /tg/Station13 (and its forks). It includes an update script that is able to update the server without having to stop or shutdown the server (the update will take effect next round) and a script to start the server and restart it if it crashes (optional, requires registry tweaks to disable the Windows crash dialog system wide) as well as systems for fixing errors and merging GitHub Pull Requests locally. + +Generally, updates force a live tracking of the configured git repo, resetting local modifications. If you plan to make modifications, set up a new git repo to store your version of the code in, and point this script to that in the config (explained below). This can be on github or a local repo using file:/// urls. + +These tools require UAC to be disabled. (There has been limited luck getting it to work under UAC on windows 10 using run as admin, but in other versions of windows, running as admin resets the current directory and this breaks things) +(Note: There is no security risk to disabling UAC because UAC is not a security boundary, there exists active unpatched exploits against it that have been around since vista and work up to windows 10) + +## Install: +1. Move this folder to where you want your server to run from (you may also rename this folder if you wish) +1. Right click on `config.bat` and select `Edit`. +1. Configure the port, git repo, and other setting, You may configure the location of git, but if you installed using git for windows, we will auto detect it if its not in path. +1. You may also need to change the location of the git repo url, and if you renamed your `dme`/"dream maker environment" file, you will need to change the project name configuration setting to be the name of your dme minus the extension (eg: if you renamed `tgstation.dme` to `ntstation.dme`, project name should be set to `ntstation` +1. Finally, run install.bat and hope for no error. + * It will clone the git repo, setup some folders, and add cross reference links everywhere. + +### Optional: +If you plan to use the `Start Server.bat` script to start the server and restart it if it crashes, you need to run the `disable crash dialog.reg` registry script to disable the "program.exe has stopped working" dialog. This will get disabled system wide so if you rely on this dialog, you should skip this step. + +## Usage: +### Folders: +* `gamecode/` + * This will house two copies of the game code, one for updating and one for live. When updating, it will automatically swap them. + +* `gamedata/` + * This contains the `data/` and `config/` folders from the code. They are stored here and a symbolic link is created in the `gamecode/` folders pointing to here. + * This also makes backing them up easy. +(you may copy and paste your existing `data/` and `config/` folders here after the install script has ran.) + +* `bot/` + * This is a copy of the bot folder. you should run the bot from here.a link to nudge.py is created in the code folders so that the game can use the announcement feature. + * The start server script and update script will send messages out thru the bot, but if its not running or python is not installed, they will gracefully continue what they are doing. + +* `gamefolder/` + * This is a symbolic link pointing to current "live" folder. + * When the server is updated, we just point this to the updating folder so that the update takes place next round. + +* `gitrepo/` + * This contains the actual git repository, all changes in here will be overwritten during update operations, the configured branch will always be forced to track from live. + * On the first update of the day, the current code state is saved to a branch called `backup-YYYY-MM-DD` before updating, to make local reverts easy. + * Following update operations on the same day do not make branches because I was too lazy to detect such edge cases. + +* `bin/` + * This contains random helper batch files. + * Running these on their own is a bad idea. + +### Starting the game server: +To run the game server, Run `Start Server.bat` + +It will restart the game server if it shutdowns for any reason, with delays if the game server had recently been (re)started. + + +### Updating the server: +To update the server, just run `Update Server.bat`. (it will git pull, compile, all that jazz) + +(Note: Updating automatically does a code reset, clearing ALL changes to the local git repo, including test merges (explained below) and manual changes (This will not change any configs/settings or clear any data in the `gamedata/` folder)) + +Updates do not require the server to be shutdown, changes will apply next round if the server is currently running. + +Updates create a branch with the current state of the repo called `backup-YYYY-MM-DD` (only one is created in any given day) + +There is also a `Update without resetting.bat` file that does the same without resetting the code, used to update without clearing test merges or local changes. Prone to merge conflicts. + + +### Locally merge GitHub Pull Requests (PR test merge): +This feature currently only works if github is the remote(git server), it could be adapted for gitlab as well. + +Running these will merge the pull request then recompile the server, changes take effect the next round if the server is currently running. + +There are multiple flavors: +* `Update To PR.bat` + * Updates the server, resetting state, and merges a PR(Pull Request) by number. +* `Merge PR Without Updating.bat` + * Merges a PR without updating the server before hand or resetting the state (can be used to test merge multiple PRs). + +You can clear all active test merges using `Reset and Recompile.bat` (explained below) + +### Resetting, Recompiling, and troubleshooting. +* `Recompile.bat` + * Just recompiles the game code and stages it to apply next round +* `Reset and Recompile.bat` + * Like the above but resets the git repo to the state of the last update operation (clearing any changes or test merges) (Does not reset `gamedata/` data/settings) + * Generally used to clear out test merges +* `Fix Errors.bat` + * Requires the server not be running, rebuilds the staging A/B folders and then does all of the above. (Used to fix errors that can prevent the server from starting or cause it to crash on reboot) + +### Using the bot +1. Install python 3 +1. Edit the config in `bot/` as needed +1. Start the bot using the `Start Bot.bat` file + + +### Starting everything when the computer/server boots +1. Use autologin to set it up so the user account logs in at boot + * (There are some security implications with doing this, this is only a tiny bit more secure then putting a file on the hard drive with the server's remote login password titled `totally not a password.txt`) + * https://technet.microsoft.com/en-us/sysinternals/bb963905 +1. Setup something to run OnServerBoot.bat on login (setting up a link/shortcut to this file in the startup folder of the start menu works, creating a scheduled task in windows administrative tools also works) +1. OnServerBoot.bat does not update, but it does re-compile and reinitialize the A/B folders. + +### Updating byond after this is all setup +1. Download installer from byond website +1. Close watch dog/start server script +1. Wait for current round to end +1. Exit DreamDeamon +1. Run installer +1. After installing, run recompile.bat (or update if you want) +1. Run start server.bat + + + + diff --git a/tools/tgstation-server/README.txt b/tools/tgstation-server/README.txt deleted file mode 100644 index 5f8d0c143a..0000000000 --- a/tools/tgstation-server/README.txt +++ /dev/null @@ -1,56 +0,0 @@ -About: - This is a toolset to manage a production server of tgstation13 (or its forks). It includes an update script that is able to update the server without having to stop or shutdown the server (the update will take effect next round) and a script to start the server and restart it if it crashes (optional, requires registry tweaks to disable the Windows crash dialog system wide) - - This will force a live tracking of the configured git repo, so no local modifications are allowed. (this is to avoid issues with merge conflicts and because I'm too lazy to make the script detect them) - - -Install: - Move this folder to where you want your server to run from (you may also rename this folder if you wish) - Right click on config.bat and click edit. - Configure the port, selected map file, and the like, You may configure the location of git, but if you installed using git for windows, we will auto detect it if its not in path. - You may also need to change the location of the gitrepo url, and if you renamed your dme/"dream maker environment" file, you will need to change the project name configuration setting to be the name of your dme minus the extension (eg: if you renamed tgstation.dme to ntstation.dme, project name should be set to ntstation - - After that, just run install.bat and hope for no error. - - It will clone the git repo, setup some folders, and add cross reference links everywhere. - - Optional: - If you plan to use the start-server script to watch the server and restart it if it crashes, you should run the "disable crash dialog.reg" registry script to disable the "program.exe has stopped working" dialog. This will get disabled system wide so if you rely on this dialog, you shouldn't run the script. - Even without this, byond stopping the world from two many critical errors (like infinite loops and recursions) will still be detected. - -Usage: - The install script will make a few folders: - gamecode - This will house two copies of the game code, one for updating and one for live. When updating, it will automatically swap them. - - gamedata - This contains the data, config, and cfg folders from the code. They are stored here and a symbolic link is created in the code folders pointing to here. - This also makes backing them up easy. - (you may copy and paste your existing data/config/cfg folders here after the install script has ran.) - - bot - This is a copy of the bot folder. you should run the bot from here. a link to coredata.py and nudge.py is created in the code folders so that the game can use the announcement feature. - The start server script and update script will send messages out thru the bot, but if its not running or python is not installed, they will gracefully continue what they are doing. - - gamefolder - This is a symbolic link pointing to current "live" folder. - When the server is updated, we just point this to the updating folder so that the update takes place next round. - - bin - This contains random helper batch files. - Running these on their own is a bad idea. - - To update the server, just run update server.bat. (it will git pull, compile, all that jazz) - It will ask you if you want to apply the update live. 99.9% of the time, this will not cause issues. The only issues it can cause relate to changes to media files(images(but not icons)/css/html/sound not stored in the RSC. but only new clients will see those issues, and at worst, its a minor graphical glitch. - You may remove the pause in the update script at line 90 if you like. - - To run the server, just run start server.bat - It will automatically redirect the runtimes to data/logs/runtimes/runtime-YYYY-MM-DD.log. - (Note: It will not automatically roll them over, but every time it crashes or stops it will have a new log file.) - When it starts dreamdaemon, it instructs byond to close down dreamdaemon if the world stops for any reason, this includes hitting the stop button, dreamdaemon shutting the world down because of too many runtimes/infinite loops. - If dreamdaemon ever stops while the start server script is running, the script will restart it automatically. - (Note: The script can not detect hangs or lockups) - - - - \ No newline at end of file diff --git a/tools/tgstation-server/Recompile.bat b/tools/tgstation-server/Recompile.bat new file mode 100644 index 0000000000..40b746365e --- /dev/null +++ b/tools/tgstation-server/Recompile.bat @@ -0,0 +1,51 @@ +@echo off +@title Server Updater +set HOME = %USERPROFILE% + +call config.bat +call bin\getcurdate.bat + +echo This will handle recompiling the server, and applying the new version. +echo ready? + +timeout 120 + +if exist updating.lk ( + echo ERROR: A current update script has been detected running. if you know this is a mistake: + pause + echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: + pause +) + +echo lock>updating.lk + +rem if the first arg to nudge.py is not a channel, it is treated as the "source" +if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" + +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Recompile job started" >nul 2>nul + +call bin\findab.bat + +call bin\copyfromgit.bat + +echo compiling change log +cd gamecode\%AB% +call python tools\ss13_genchangelog.py html/changelog.html html/changelogs +cd ..\.. + +echo Compiling game. +call bin\build.bat +if %DM_EXIT% neq 0 ( + echo DM compile failed. Aborting. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed Aborting recompile." >nul 2>nul + del /F /Q updating.lk >nul 2>nul + pause + exit /b 1 +) + +del updating.lk >nul 2>nul +rmdir /q gamefolder +mklink /d gamefolder gamecode\%AB% >nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Recompile finished. Recompiled code will take place next round." >nul 2>nul +echo Done. The recompile will automatically take place at round restart. +timeout 300 \ No newline at end of file diff --git a/tools/tgstation-server/Reset and Recompile.bat b/tools/tgstation-server/Reset and Recompile.bat new file mode 100644 index 0000000000..f0127fd3ac --- /dev/null +++ b/tools/tgstation-server/Reset and Recompile.bat @@ -0,0 +1,66 @@ +@echo off +@title Server Updater +set HOME = %USERPROFILE% + +call config.bat +call bin\getcurdate.bat +call bin\findgit.bat + +echo This will handle resetting the git repo, recompiling the server, and applying the new version. +echo Ready? + +timeout 120 + +if exist updating.lk ( + echo ERROR: A current update script has been detected running. if you know this is a mistake: + pause + echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: + pause +) + +echo lock>updating.lk + +rem if the first arg to nudge.py is not a channel, it is treated as the "source" +if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" + +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Reset local changes job started" >nul 2>nul + +cd gitrepo +git reset --hard +git clean -df +cd .. +echo ################################## +echo ################################## +echo: +echo Resetting done, compiling in 10 seconds. If you want to preform other actions (like test merges) You can close this now and do them. +echo: +del updating.lk >nul 2>nul + +timeout 10 + +echo lock>updating.lk +call bin\findab.bat + +call bin\copyfromgit.bat + +echo compiling change log +cd gamecode\%AB% +call python tools\ss13_genchangelog.py html/changelog.html html/changelogs +cd ..\.. + +echo Compiling game. +call bin\build.bat +if %DM_EXIT% neq 0 ( + echo DM compile failed. Aborting. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed Aborting Reset." >nul 2>nul + del /F /Q updating.lk >nul 2>nul + pause + exit /b 1 +) + +del updating.lk >nul 2>nul +rmdir /q gamefolder +mklink /d gamefolder gamecode\%AB% >nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Reset finished. Reset will take place next round." >nul 2>nul +echo Done. The Reset will automatically take place at round restart. +timeout 300 diff --git a/tools/tgstation-server/Start Bot.bat b/tools/tgstation-server/Start Bot.bat index c0631dabbf..a3b1cba0d8 100644 --- a/tools/tgstation-server/Start Bot.bat +++ b/tools/tgstation-server/Start Bot.bat @@ -1,7 +1,7 @@ @echo off @title NT IRC BOT -echo Welcome to the start bot script, This will start the bot and make sure it stays running. This assumes python in the path. To continue, press any key or wait 60 seconds. -timeout 60 +echo Welcome to the start bot script, This will start the bot and make sure it stays running. This assumes python in the path. To continue, press any key or wait 15 seconds. +timeout 15 cd bot :START call ..\bin\getcurdate.bat @@ -9,7 +9,7 @@ if not exist ..\gamedata\data\logs\bot mkdir ..\gamedata\data\logs\bot\ cls echo NT IRC Bot echo Bot Running. Watching for Bot exits. -start /WAIT python NanoTrasenBot.py >>..\gamedata\data\logs\bot\bot-%CUR_DATE%.txt +start /WAIT python minibot.py ^>^>..\gamedata\data\logs\bot\bot-%CUR_DATE%.txt cls echo NT IRC Bot echo Bot exit detected. Restarting in 15 minutes. diff --git a/tools/tgstation-server/Start Server.bat b/tools/tgstation-server/Start Server.bat index 26d3008b34..80efb9444b 100644 --- a/tools/tgstation-server/Start Server.bat +++ b/tools/tgstation-server/Start Server.bat @@ -3,22 +3,37 @@ call config.bat call bin\findbyond.bat -echo Welcome to the start server watch dog script, This will start the server and make sure it stays running. To continue, press any key or wait 60 seconds. -timeout 60 +echo Welcome to the start server watch dog script, This will start the server and make sure it stays running. To continue, press any key or wait 30 seconds. +timeout 30 if not exist gamedata\data\logs\runtimes mkdir gamedata\data\logs\runtimes\ -@python bot\nudge.py "WATCHDOG" "Watch Dog online. Starting server" >nul 2>nul +@call python bot\nudge.py "WATCHDOG" "Watch Dog online. Starting server" >nul 2>nul :START + call bin\getcurdate.bat + +call bin\getunixtime.bat UNIXTIME + +echo %UNIXTIME% + +set STARTTIME=%UNIXTIME% + cls echo Watch Dog. echo Server Running. Watching for server exits. -start /WAIT /ABOVENORMAL "" dreamdaemon.exe gamefolder\%PROJECTNAME%.dmb -port %PORT% -trusted -public -close -log "data\logs\runtimes\runtime-%CUR_DATE%.log" +start /WAIT /ABOVENORMAL "" dreamdaemon.exe gamefolder\%PROJECTNAME%.dmb -port %PORT% -trusted -close -public -verbose cls + +call bin\getunixtime.bat UNIXTIME + +SET /A Result=%UNIXTIME% - %STARTTIME% +SET /A Result=180 - (%Result%/3) +if %Result% LSS 0 set /A Result=0 + echo Watch Dog. -echo Server exit detected. Restarting in 60 seconds. -@python bot\nudge.py "WATCHDOG" "Server exit detected. Restarting server in 60 seconds." >nul 2>nul -timeout 60 +echo Server exit detected. Restarting in %Result% seconds. +@python bot\nudge.py "WATCHDOG" "Server exit detected. Restarting server in %Result% seconds." >nul 2>nul +timeout %Result% goto :START diff --git a/tools/tgstation-server/Update Server.bat b/tools/tgstation-server/Update Server.bat index f7e48f5fe8..1d7d8644af 100644 --- a/tools/tgstation-server/Update Server.bat +++ b/tools/tgstation-server/Update Server.bat @@ -1,53 +1,79 @@ @echo off -@title Server Updater +title Server Updater +SETLOCAL ENABLEDELAYEDEXPANSION set HOME = %USERPROFILE% + call config.bat call bin\getcurdate.bat + echo This will handle downloading git, compiling the server, and applying the update. -echo ready? +echo Ready? + timeout 120 + if exist updating.lk ( - echo ERROR! A current update script has been detected running. if you know this is a mistake: + echo ERROR: A current update script has been detected running. if you know this is a mistake: pause echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: pause ) + +if exist prtestjob.lk ( + call bin/activepr.bat + echo WARNING: The server is currently testing the following PRs !PR!. This update would override that. Do you still want to update? Close this window if not, otherwise: + pause +) + +del /F /Q prtestjob.lk >nul 2>nul + echo lock>updating.lk + bin/activepr.bat rem if the first arg to nudge.py is not a channel, it is treated as the "source" if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" -python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job started" >nul 2>nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job started" >nul 2>nul call bin\updategit.bat if %GIT_EXIT% neq 0 ( echo git pull failed. Aborting update - python bot\nudge.py %UPDATE_LOG_CHANNEL% "Git pull failed. Aborting update" - @del updating.lk >nul 2>nul + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Git fetch failed. Aborting update" + del updating.lk >nul 2>nul pause exit /b 1 ) + if defined PUSHCHANGELOGTOGIT ( + cd gitrepo echo compiling change log python tools\ss13_genchangelog.py html/changelog.html html/changelogs - if %ERRORLEVEL% == 0 ( + if !ERRORLEVEL! == 0 ( echo pushing compiled changelog to server git add -u html/changelog.html git add -u html/changelogs git commit -m "Automatic changelog compile, [ci skip]" - if %ERRORLEVEL% == 0 ( + if !ERRORLEVEL! == 0 ( git push ) REM an error here generally means there was nothing to commit. ) + cd .. ) +echo ################################## +echo ################################## +echo: +echo Updating done, compiling in 10 seconds. If you want to preform other actions (like test merge) You can close this now and do them. +echo: +del updating.lk >nul 2>nul + +timeout 10 + +echo lock>updating.lk call bin\findab.bat call bin\copyfromgit.bat - - if not defined PUSHCHANGELOGTOGIT ( echo compiling change log cd gamecode\%AB% @@ -55,26 +81,19 @@ if not defined PUSHCHANGELOGTOGIT ( cd ..\.. ) - - -echo building script. +echo Compiling game. call bin\build.bat if %DM_EXIT% neq 0 ( echo DM compile failed. Aborting. - python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed Aborting update." >nul 2>nul - @del /F /Q updating.lk >nul 2>nul + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed Aborting update." >nul 2>nul + del /F /Q updating.lk >nul 2>nul pause exit /b 1 ) -if not defined NOWAITUPDATES ( - echo OK, compiled and ready. So at the hit of a button, we can apply the update live. Technically speaking, it's best to wait until near round end, but unless a html/css/js file in the code had been deleted, edited, or moved recently, no ill effects of applying the update will happen, and the worst is that new clients have display oddities relating to in game windows. Existing connections should have no issue. - echo Ready? - pause -) -@del updating.lk >nul 2>nul +del updating.lk >nul 2>nul rmdir /q gamefolder mklink /d gamefolder gamecode\%AB% >nul -python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job finished. Update will take place next round." >nul 2>nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job finished. Update will take place next round." >nul 2>nul echo Done. The update will automatically take place at round restart. timeout 300 \ No newline at end of file diff --git a/tools/tgstation-server/Update to PR.bat b/tools/tgstation-server/Update to PR.bat new file mode 100644 index 0000000000..b6c57b98b7 --- /dev/null +++ b/tools/tgstation-server/Update to PR.bat @@ -0,0 +1,121 @@ +@echo off +title Server Updater +SETLOCAL ENABLEDELAYEDEXPANSION +set HOME = %USERPROFILE% + +call config.bat +rem if the first arg to nudge.py is not a channel, it is treated as the "source" +if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" +call bin\getcurdate.bat +call bin\findgit.bat +echo This will handle Resetting the repo downloading from git, merging the pr locally, compiling the server, and applying the PR test job. + +:PROMPT +SET /P UserInput=Please enter the pr number (without a # or anything of the sorts): +SET /A PR=UserInput + +if %PR% EQU %UserInput% ( + if %PR% GTR 0 ( + echo updating to pr %PR% + ) else ( + echo Bad input + goto PROMPT + ) +) else ( + echo Bad input + goto PROMPT +) +if exist updating.lk ( + echo ERROR: A current update script has been detected running. if you know this is a mistake: + pause + echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: + pause +) + +echo lock>updating.lk + bin/activepr.bat +del /F /Q prtestjob.lk >nul 2>nul + +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "PR test job started. Updating master and merging PR #%PR% locally" >nul 2>nul + +call bin\updategit.bat +if %GIT_EXIT% neq 0 ( + echo git pull failed. Aborting update + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Git fetch failed. Aborting update" + del updating.lk >nul 2>nul + pause + exit /b 1 +) + +if defined PUSHCHANGELOGTOGIT ( + cd gitrepo + echo compiling change log + call python tools\ss13_genchangelog.py html/changelog.html html/changelogs + if !ERRORLEVEL! == 0 ( + echo pushing compiled changelog to server + git add -u html/changelog.html + git add -u html/changelogs + git commit -m "Automatic changelog compile, [ci skip]" + if !ERRORLEVEL! == 0 ( + git push + ) + REM an error here generally means there was nothing to commit. + ) + cd .. +) + +cd gitrepo +git fetch origin pull/%PR%/head:pr-%PR% +git merge pr-%PR% +if %ERRORLEVEL% neq 0 ( + git reset --hard + git clean -fd + cd .. + echo git merge of PR #%PR% failed. Aborting test merge. + echo An update was successfully preformed but not applied, if you want you can apply it by running recompile.bat + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "git merge of PR #%PR% failed. Aborting PR test job" >nul 2>nul + del updating.lk >nul 2>nul + pause + exit /b 1 +) +cd .. + +echo %PR%>prtestjob.lk +> bin/activepr.bat + +echo ################################## +echo ################################## +echo: +echo Updating to pr done, compiling in 10 seconds. If you want to preform other actions (like more test merges) You can close this now and do them. +echo: +del updating.lk >nul 2>nul + +timeout 10 + +echo lock>updating.lk +call bin\findab.bat + +call bin\copyfromgit.bat + + +echo compiling change log (again) +cd gamecode\%AB% +call python tools\ss13_genchangelog.py html/changelog.html html/changelogs +cd ..\.. + +echo Compiling game. +call bin\build.bat +if %DM_EXIT% neq 0 ( + echo DM compile failed. Aborting. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed. Aborting test merge." >nul 2>nul + del /F /Q updating.lk >nul 2>nul + pause + exit /b 1 +) + +del updating.lk >nul 2>nul +rmdir /q gamefolder +mklink /d gamefolder gamecode\%AB% >nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Test merge job finished. Test merge will take place next round." >nul 2>nul +echo Done. The test merge will automatically take place at round restart. +timeout 300 \ No newline at end of file diff --git a/tools/tgstation-server/Update without resetting.bat b/tools/tgstation-server/Update without resetting.bat new file mode 100644 index 0000000000..9a08573fb1 --- /dev/null +++ b/tools/tgstation-server/Update without resetting.bat @@ -0,0 +1,100 @@ +@echo off +@title Server Updater +SETLOCAL ENABLEDELAYEDEXPANSION +set HOME = %USERPROFILE% + +call config.bat +call bin\getcurdate.bat +call bin\findgit.bat + +echo This will update the server without resetting local changes like test merges. +echo Note: This doesn't update the changelog like a normal update does. +echo Ready? + +timeout 120 + +if exist updating.lk ( + echo ERROR: A current update script has been detected running. if you know this is a mistake: + pause + echo Please be double sure that an update script is not currently running, if you think one might be, close this window. otherwise: + pause +) + +echo lock>updating.lk + +rem if the first arg to nudge.py is not a channel, it is treated as the "source" +if not defined UPDATE_LOG_CHANNEL set UPDATE_LOG_CHANNEL="UPDATER" + +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job started (No reset mode)" >nul 2>nul + +cd gitrepo +git fetch origin +if %ERRORLEVEL% neq 0 ( + cd .. + echo git fetch failed. Aborting update. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Git fetch failed. Aborting update" + del updating.lk >nul 2>nul + pause + exit /b 1 +) +git merge origin/%REPO_BRANCH% +if %ERRORLEVEL% neq 0 ( + cd .. + echo git merge of upstream master failed, aborting update. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "git merge of upstream master failed, aborting update." >nul 2>nul + cd gitrepo + git merge --abort + if %ERRORLEVEL% neq 0 ( + echo ERROR: Error aborting update, resetting repo. + cd .. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Error aborting merge, Resetting git repo" >nul 2>nul + cd gitrepo + git reset --hard + git clean -fd + bin/activepr.bat + del /F /Q prtestjob.lk >nul 2>nul + echo NOTICE: We had to reset the repo's state, all active test merges were undone. + ) + cd .. + del updating.lk >nul 2>nul + pause + exit /b 1 +) +cd .. + + +echo ################################## +echo ################################## +echo: +echo In place update done, compiling in 10 seconds. If you want to preform other actions (like more test merges) You can close this now and do them. +echo: +del updating.lk >nul 2>nul + +timeout 10 + +echo lock>updating.lk +call bin\findab.bat + +call bin\copyfromgit.bat + +echo compiling change log +cd gamecode\%AB% +call python tools\ss13_genchangelog.py html/changelog.html html/changelogs +cd ..\.. + +echo Compiling game. +call bin\build.bat +if %DM_EXIT% neq 0 ( + echo DM compile failed. Aborting. + call python bot\nudge.py %UPDATE_LOG_CHANNEL% "DM compile failed Aborting update." >nul 2>nul + del /F /Q updating.lk >nul 2>nul + pause + exit /b 1 +) + +del updating.lk >nul 2>nul +rmdir /q gamefolder +mklink /d gamefolder gamecode\%AB% >nul +call python bot\nudge.py %UPDATE_LOG_CHANNEL% "Update job finished. Update will take place next round." >nul 2>nul +echo Done. The update will automatically take place at round restart. +timeout 300 diff --git a/tools/tgstation-server/bin/activepr.bat b/tools/tgstation-server/bin/activepr.bat new file mode 100644 index 0000000000..554142925d --- /dev/null +++ b/tools/tgstation-server/bin/activepr.bat @@ -0,0 +1 @@ +set PR= \ No newline at end of file diff --git a/tools/tgstation-server/bin/build.bat b/tools/tgstation-server/bin/build.bat index 6b9163fe86..049154ce92 100644 --- a/tools/tgstation-server/bin/build.bat +++ b/tools/tgstation-server/bin/build.bat @@ -1,4 +1,3 @@ -@echo off call config.bat call bin/findbyond.bat set DME_FOLDER=gamefolder\ @@ -7,11 +6,19 @@ if defined AB set DME_FOLDER=gamecode\%AB%\ set DME_LOCATION=%DME_FOLDER%%PROJECTNAME%.dme set MDME_LOCATION=%DME_FOLDER%%PROJECTNAME%.mdme +@del %MDME_LOCATION% >nul 2>nul +if defined MAPROTATE set MAPFILE=%MAPROTATE% +if not defined MAPFILE goto BUILD + +echo #define MAP_OVERRIDE >>%MDME_LOCATION% +echo #include "_maps\%MAPFILE%.dm" >>%MDME_LOCATION% + :BUILD echo #define SERVERTOOLS 1 >>%MDME_LOCATION% +echo #define PUTONHUB 1 >>%MDME_LOCATION% type %DME_LOCATION% >>%MDME_LOCATION% -dm %MDME_LOCATION% +dm -clean %MDME_LOCATION% set DM_EXIT=%ERRORLEVEL% @del %DME_FOLDER%%PROJECTNAME%.dmb >nul 2>nul @del %DME_FOLDER%%PROJECTNAME%.rsc >nul 2>nul diff --git a/tools/tgstation-server/bin/copyfromgit.bat b/tools/tgstation-server/bin/copyfromgit.bat index 9f25dcad98..4de01db772 100644 --- a/tools/tgstation-server/bin/copyfromgit.bat +++ b/tools/tgstation-server/bin/copyfromgit.bat @@ -2,11 +2,10 @@ echo Removing old files rem delete the symlinks manually to ensure their targets don't get recursively deleted rmdir /q gamecode\%AB%\data >nul 2>nul rmdir /q gamecode\%AB%\config >nul 2>nul -rmdir /q gamecode\%AB%\cfg >nul 2>nul del /q gamecode\%AB%\nudge.py >nul 2>nul -del /q gamecode\%AB%\CORE_DATA.py >nul 2>nul +del /q gamecode\%AB%\libmysql.dll >nul 2>nul -del /S /F /Q gamecode\%AB% >nul 2>nul +del /S /F /Q gamecode\%AB%\ >nul 2>nul echo Copying files xcopy gitrepo gamecode\%AB% /Y /X /K /R /H /I /C /V /E /Q /EXCLUDE:copyexclude.txt >nul @@ -14,9 +13,8 @@ mkdir gamecode\%AB%\.git\logs copy gitrepo\.git\logs\HEAD gamecode\%AB%\.git\logs\HEAD /D /V /Y >nul mklink gamecode\%AB%\nudge.py ..\..\bot\nudge.py >nul -mklink gamecode\%AB%\CORE_DATA.py ..\..\bot\CORE_DATA.py >nul rmdir /q gamecode\%AB%\data >nul 2>nul rmdir /s /q gamecode\%AB%\data >nul 2>nul mklink /d gamecode\%AB%\data ..\..\gamedata\data >nul mklink /d gamecode\%AB%\config ..\..\gamedata\config >nul -mklink /d gamecode\%AB%\cfg ..\..\gamedata\cfg >nul \ No newline at end of file +mklink gamecode\%AB%\libmysql.dll ..\..\gamedata\libmysql.dll >nul diff --git a/tools/tgstation-server/bin/findab.bat b/tools/tgstation-server/bin/findab.bat index 9bb94bed14..0c24a7571b 100644 --- a/tools/tgstation-server/bin/findab.bat +++ b/tools/tgstation-server/bin/findab.bat @@ -1,5 +1,5 @@ -@del gamecode\a\updater.temp >nul 2>nul -@del gamecode\b\updater.temp >nul 2>nul +del gamecode\a\updater.temp >nul 2>nul +del gamecode\b\updater.temp >nul 2>nul echo test >gamefolder\updater.temp @@ -15,6 +15,14 @@ if exist gamecode\a\updater.temp ( set AB=b ) else ( echo Current folder detected to be the "A" folder. Game is not currently running, Updating to the "A" folder. + if exist gamecode\b\%PROJECTNAME%.rsc.lk ( + rem we attempt to delete the lock file to see if the server is currently running. + del /q gamecode\b\%PROJECTNAME%.rsc.lk >nul 2>nul + if exist gamecode\b\%PROJECTNAME%.rsc.lk set RUNNING=1 + rmdir /q gamefolder + mklink /d gamefolder gamecode\b >nul + echo Game is in actually currently running on the "B" folder, Resetting current folder to the "B" folder first + ) set AB=a ) ) else if exist gamecode\b\updater.temp ( @@ -23,7 +31,15 @@ if exist gamecode\a\updater.temp ( set AB=a ) else ( echo Current folder detected to be the "B" folder. Game is not currently running, Updating to the "B" folder. + if exist gamecode\a\%PROJECTNAME%.rsc.lk ( + rem we attempt to delete the lock file to see if the server is currently running. + del /q gamecode\a\%PROJECTNAME%.rsc.lk >nul 2>nul + if exist gamecode\a\%PROJECTNAME%.rsc.lk set RUNNING=1 + rmdir /q gamefolder + mklink /d gamefolder gamecode\a >nul + echo Game is in actually currently running on the "A" folder, Resetting current folder to the "A" folder first + ) set AB=b ) ) -@del gamefolder\updater.temp >nul 2>nul \ No newline at end of file +del gamefolder\updater.temp >nul 2>nul \ No newline at end of file diff --git a/tools/tgstation-server/bin/findbyond.bat b/tools/tgstation-server/bin/findbyond.bat index 2e015e4e62..ff07af2dd6 100644 --- a/tools/tgstation-server/bin/findbyond.bat +++ b/tools/tgstation-server/bin/findbyond.bat @@ -1,4 +1,3 @@ -@echo off @dm.exe -h >nul 2>nul IF %ERRORLEVEL% NEQ 9009 ( diff --git a/tools/tgstation-server/bin/findgit.bat b/tools/tgstation-server/bin/findgit.bat index 059dfd6626..9c802b54c6 100644 --- a/tools/tgstation-server/bin/findgit.bat +++ b/tools/tgstation-server/bin/findgit.bat @@ -1,4 +1,3 @@ -@echo off REM check if git is already in path git --version >nul 2>nul && goto :eof diff --git a/tools/tgstation-server/bin/getcurdate.bat b/tools/tgstation-server/bin/getcurdate.bat index 84c19f7dd5..f5360756ce 100644 --- a/tools/tgstation-server/bin/getcurdate.bat +++ b/tools/tgstation-server/bin/getcurdate.bat @@ -1,3 +1,2 @@ -@echo off FOR /f %%a in ('WMIC OS GET LocalDateTime ^| find "."') DO set DTS=%%a set CUR_DATE=%DTS:~0,4%-%DTS:~4,2%-%DTS:~6,2% \ No newline at end of file diff --git a/tools/tgstation-server/bin/getunixtime.bat b/tools/tgstation-server/bin/getunixtime.bat index 64672391e8..2b4115faab 100644 --- a/tools/tgstation-server/bin/getunixtime.bat +++ b/tools/tgstation-server/bin/getunixtime.bat @@ -1,2 +1,12 @@ -@echo off -for /f "delims=" %%x in ('cscript /nologo unixtime.vbs') do set UNIXTIME=%%x \ No newline at end of file +REM setlocal +call :GetUnixTime UNIXTIME +goto :EOF + +:GetUnixTime +REM setlocal enableextensions +for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do ( + set %%x) +set /a z=(14-100%Month%%%100)/12, y=10000%Year%%%10000-z +set /a ut=y*365+y/4-y/100+y/400+(153*(100%Month%%%100+12*z-3)+2)/5+Day-719469 +set /a ut=ut*86400+100%Hour%%%100*3600+100%Minute%%%100*60+100%Second%%%100 +endlocal & set "%1=%ut%" & goto :EOF \ No newline at end of file diff --git a/tools/tgstation-server/bin/updategit.bat b/tools/tgstation-server/bin/updategit.bat index 024e17dfed..e16cfc3922 100644 --- a/tools/tgstation-server/bin/updategit.bat +++ b/tools/tgstation-server/bin/updategit.bat @@ -1,18 +1,12 @@ call bin\findgit.bat echo Updating repo + cd gitrepo + git branch backup-%CUR_DATE% >nul 2>nul git fetch set GIT_EXIT=%ERRORLEVEL% -if %GIT_EXIT% neq 0 goto END -git checkout %REPO_BRANCH% -set GIT_EXIT=%ERRORLEVEL% -if %GIT_EXIT% neq 0 goto END -git reset origin/%REPO_BRANCH% --hard -set GIT_EXIT=%ERRORLEVEL% -if %GIT_EXIT% neq 0 goto END -git pull --force -set GIT_EXIT=%ERRORLEVEL% -:END +git reset origin/%REPO_BRANCH% --hard + cd .. \ No newline at end of file diff --git a/tools/tgstation-server/config.bat b/tools/tgstation-server/config.bat index 201c17abbe..eb3ecd13e7 100644 --- a/tools/tgstation-server/config.bat +++ b/tools/tgstation-server/config.bat @@ -1,50 +1,42 @@ @echo off -REM Server Tools configuration file. Lines starting with REM are comments and ignored. -REM on/off config options are considered "on" if they have anything (even 0) and "off" if they are blank or commented out. +REM Server Tools configuration file. Lines starting with rem are comments and ignored. REM This must be set to the name of your dme without the .dme part. (should be fine leaving this alone unless you renamed the code) set PROJECTNAME=tgstation -REM location of the repo. +REM location of the repo. (use an ssh url if you plan to push compiled changlogs) +REM Only set during install, do not re-run install.bat if you change this, instead manually change the remote of the gitrepo folder using git tools set REPO_URL=https://github.com/tgstation/-tg-station.git -REM set REPO_URL=git@github.com:tgstation/-tg-station.git REM What branch of the repo to use. set REPO_BRANCH=master -REM what map file to use. This should be the name of the dm, not dmm (and without the .dm part) (defaults to what ever is ticked in the dme) -set MAPFILE=tgstation2 +REM Override Map (This disables map roation and forces the selected map to always be loaded) +REM set MAPFILE=tgstation2 REM set MAPFILE=metastation -REM set MAPFILE=ministation -REM port to use (only used to start the server in the start-server script) -set PORT=1337 +REM port to use when starting the server +set PORT=2337 -REM This is the channel to log updates to. Leave blank to log to the normal channel (this is done via the tgstation bot, optional) -set UPDATE_LOG_CHANNEL=#coderbus - - -REM overrides the prompt to live apply the updates in update server.bat if set to anything other than a null string. -REM It is generally safe to live apply the updates, they don't take effect until the next round. the only concern is that some media files may get loaded by new clients before the next round. These files aren't edited 99% of the time, so its not a real concern, but I kept the prompt the default for compatibility sake. -set NOWAITUPDATES= +REM This is the channel to log updates to. Leave blank to log to the bot's default logging channel (this is done via the tgstation minibot bot, optional) +set UPDATE_LOG_CHANNEL=#devbus,#coderbus,#tgstation13 REM Attempt to push the compiled changelog to the configured git server? (set to anything) -REM This requires you configure git with authentication for the upstream server. (the ssh key should be stored in c:\users\USERNAME_HERE\.ssh\ as the filename id_rsa (if that still doesn't work, try c:\program files\git\.ssh\id_rsa)) +REM This requires you configure git with authentication for the upstream server. (git for windows users should just put an ssh key in c:\users\USERNAME_HERE\.ssh\ as the filename id_rsa) And you should have installed this with a git, ssh, or file url) set PUSHCHANGELOGTOGIT= REM location of git. The script will attempt to auto detect this, but if it fails, you can set it manually. -REM This will be added to the end of path as is (only for the batch file, not the whole system) REM github for windows users see http://www.chambaud.com/2013/07/08/adding-git-to-path-when-using-github-for-windows/ (an example is provided below) + set GIT_LOCATION_PATH= -REM set GIT_LOCATION_PATH=C:\Users\\AppData\Local\GitHub\PortableGit_\bin;C:\Users\\AppData\Local\GitHub\PortableGit_\cmd +REM set GIT_LOCATION_PATH=C:\Users\Administrator\AppData\Local\GitHub\PortableGit_c2ba306e536fdf878271f7fe636a147ff37326ad\bin;C:\Users\Administrator\AppData\Local\GitHub\PortableGit_c2ba306e536fdf878271f7fe636a147ff37326ad\cmd - -REM path to the byond bin folder. (if blank, we look in path, program files/byond/bin, and program files (x86)/byond/bin) (same rules as git path above) -set BYOND_LOCATION_PATH= \ No newline at end of file +REM path to the byond bin folder. (same rules as git path above, almost always auto detected, but you could point this to the output of the zip version for install-less setups, and even abuse that to make updating byond versions less of a pain by just changing this config and then crashing the server.) +set BYOND_LOCATION_PATH= diff --git a/tools/tgstation-server/copyexclude.txt b/tools/tgstation-server/copyexclude.txt index a790724e14..3cf4643303 100644 --- a/tools/tgstation-server/copyexclude.txt +++ b/tools/tgstation-server/copyexclude.txt @@ -4,6 +4,6 @@ gitrepo\config\ gitrepo\data\ gitrepo\bot\ -gitrepo\cfg\ gitrepo\.git\ +gitrepo\libmysql.dll diff --git a/tools/tgstation-server/install.bat b/tools/tgstation-server/install.bat index e6089b0497..f37908966a 100644 --- a/tools/tgstation-server/install.bat +++ b/tools/tgstation-server/install.bat @@ -29,7 +29,6 @@ echo Repo downloaded. echo Setting up folders... mkdir gamecode\a mkdir gamecode\b -mkdir gamecode\override mkdir gamedata mkdir bot @@ -37,8 +36,8 @@ echo Copying things around.... echo (1/3) xcopy gitrepo\data gamedata\data /Y /X /K /R /H /I /C /V /E /Q >nul xcopy gitrepo\config gamedata\config /Y /X /K /R /H /I /C /V /E /Q >nul -xcopy gitrepo\cfg gamedata\cfg /Y /X /K /R /H /I /C /V /E /Q >nul xcopy gitrepo\bot bot /Y /X /K /R /H /I /C /V /E /Q >nul +copy gitrepo\libmysql.dll gamedata\libmysql.dll /D /V /Y >nul echo (2/3) xcopy gitrepo gamecode\a /Y /X /K /R /H /I /C /V /E /Q /EXCLUDE:copyexclude.txt >nul mkdir gamecode\a\.git\logs\ @@ -51,25 +50,27 @@ echo done. echo Setting up symbolic links. mklink gamecode\a\nudge.py ..\..\bot\nudge.py -mklink gamecode\a\CORE_DATA.py ..\..\bot\CORE_DATA.py +mklink gamecode\a\libmysql.dll ..\..\gamedata\libmysql.dll mklink /d gamecode\a\data ..\..\gamedata\data mklink /d gamecode\a\config ..\..\gamedata\config -mklink /d gamecode\a\cfg ..\..\gamedata\cfg mklink gamecode\b\nudge.py ..\..\bot\nudge.py -mklink gamecode\b\CORE_DATA.py ..\..\bot\CORE_DATA.py +mklink gamecode\b\libmysql.dll ..\..\gamedata\libmysql.dll mklink /d gamecode\b\data ..\..\gamedata\data mklink /d gamecode\b\config ..\..\gamedata\config -mklink /d gamecode\b\cfg ..\..\gamedata\cfg mklink /d gamefolder gamecode\a +echo prepping python (if installed) +pip install PyYaml +pip install beautifulsoup4 + echo Compiling for the first time. echo Compiling change log. -cd gamecode\a +cd gamefolder call python tools\ss13_genchangelog.py html/changelog.html html/changelogs -cd ..\.. +cd .. echo Compiling game. call bin\build.bat if %DM_EXIT% neq 0 echo DM compile failed. @@ -77,4 +78,4 @@ if %DM_EXIT% neq 0 echo DM compile failed. echo Done. You may start the server using the start server program or change the game config in gamedata\config pause -:ABORT \ No newline at end of file +:ABORT