diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 3aa638aa40f..a7678e1d261 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -18,7 +18,7 @@ return -/client/proc/debug_controller(controller in list("Master","failsafe","Ticker","Air","Lighting","Jobs","Sun","Radio","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event","Alarm","Scheduler","Nano","Vote")) +/client/proc/debug_controller(controller in list("Master","failsafe","Ticker","Air","Lighting","Jobs","Sun","Radio","Configuration","pAI", "Cameras","Garbage", "Transfer Controller","Event","Alarm","Scheduler","Nano","Vote","Mob Hunt Server")) set category = "Debug" set name = "Debug Controller" set desc = "Debug the various periodic loop controllers for the game (be careful!)" @@ -76,6 +76,9 @@ if("Vote") debug_variables(vote) feedback_add_details("admin_verb","DVote") + if("Mob Hunt Server") + debug_variables(mob_hunt_server) + feedback_add_details("admin_verb","DMobHuntServer") message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") return diff --git a/code/modules/arcade/mob_hunt/game_server.dm b/code/modules/arcade/mob_hunt/game_server.dm index 1f801250835..cbcaa400925 100644 --- a/code/modules/arcade/mob_hunt/game_server.dm +++ b/code/modules/arcade/mob_hunt/game_server.dm @@ -1,12 +1,6 @@ +var/global/datum/controller/process/mob_hunt/mob_hunt_server -var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null - -/obj/machinery/mob_hunt_server - name = "Nano-Mob Hunter GO Server " - desc = "A game server for the new hit PDA game \"Nano-Mob Hunter GO\". May be unstable." - icon_state = "processor" - density = 1 - anchored = 1 +/datum/controller/process/mob_hunt var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this var/list/normal_spawns = list() var/list/trap_spawns = list() @@ -14,24 +8,19 @@ var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null var/server_instability = 0 //tracks the instability of the game server. trapped mobs and users increase instability, which causes random kicks and eventually crashing var/server_status = 1 //1 is online, 0 is offline -/obj/machinery/mob_hunt_server/New() - ..() - if(!mob_hunt_server) - mob_hunt_server = src - else - log_admin("A Nano-Mob Hunter GO server was created at ([x], [y]) on z[z] while one already exists. Deleting the new server.") - //there can only be one! - qdel(src) +/datum/controller/process/mob_hunt/setup() + name = "Nano-Mob Hunter GO Server" + start_delay = 20 + mob_hunt_server = src -/obj/machinery/mob_hunt_server/Destroy() +/datum/controller/process/mob_hunt/Destroy() for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients) client.disconnect("Server Destruction") if(mob_hunt_server && mob_hunt_server == src) mob_hunt_server = null return ..() -/obj/machinery/mob_hunt_server/process() - ..() +/datum/controller/process/mob_hunt/doWork() if(server_status == 0) return if(normal_spawns.len < max_normal_spawns) @@ -48,10 +37,10 @@ var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null var/datum/data/pda/app/mob_hunter_game/client = pick(connected_clients) client.disconnect("Server Communication Error") -/obj/machinery/mob_hunt_server/proc/check_stability() +/datum/controller/process/mob_hunt/proc/check_stability() server_instability = connected_clients.len + (trap_spawns.len * 5) -/obj/machinery/mob_hunt_server/proc/server_crash() +/datum/controller/process/mob_hunt/proc/server_crash() server_status = 0 for(var/datum/data/pda/app/mob_hunter_game/client in connected_clients) client.disconnect("Server Crash") @@ -66,7 +55,7 @@ var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null //set a timer to automatically recover in 5 minutes (can be manually restarted if you get impatient too) addtimer(src, "auto_recover", 3000, TRUE) -/obj/machinery/mob_hunt_server/proc/auto_recover() +/datum/controller/process/mob_hunt/proc/auto_recover() if(server_status != 0) return server_instability = 0 @@ -74,7 +63,7 @@ var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null while(normal_spawns.len < max_normal_spawns) //repopulate the server's spawns completely if we auto-recover from crash spawn_mob() -/obj/machinery/mob_hunt_server/proc/manual_reboot() +/datum/controller/process/mob_hunt/proc/manual_reboot() for(var/obj/effect/nanomob/N in trap_spawns) N.despawn() for(var/obj/effect/nanomob/N in normal_spawns) @@ -82,19 +71,19 @@ var/global/obj/machinery/mob_hunt_server/mob_hunt_server = null check_stability() server_status = 1 -/obj/machinery/mob_hunt_server/proc/spawn_mob() +/datum/controller/process/mob_hunt/proc/spawn_mob() var/list/nanomob_types = subtypesof(/datum/mob_hunt) var/datum/mob_hunt/mob_info = pick(nanomob_types) new mob_info() -/obj/machinery/mob_hunt_server/proc/register_spawn(datum/mob_hunt/mob_info) +/datum/controller/process/mob_hunt/proc/register_spawn(datum/mob_hunt/mob_info) if(!mob_info) return 0 var/obj/effect/nanomob/new_mob = new /obj/effect/nanomob(mob_info.spawn_point, mob_info) normal_spawns += new_mob return 1 -/obj/machinery/mob_hunt_server/proc/register_trap(datum/mob_hunt/mob_info) +/datum/controller/process/mob_hunt/proc/register_trap(datum/mob_hunt/mob_info) if(!mob_info) return 0 if(!mob_info.is_trap) diff --git a/code/modules/arcade/mob_hunt/mob_avatar.dm b/code/modules/arcade/mob_hunt/mob_avatar.dm index 3d5ad935d58..085d2a7f6bc 100644 --- a/code/modules/arcade/mob_hunt/mob_avatar.dm +++ b/code/modules/arcade/mob_hunt/mob_avatar.dm @@ -37,27 +37,25 @@ return if(istype(O, /obj/item/device/pda)) var/obj/item/device/pda/P = O - if(P.current_app && istype(P.current_app, /datum/data/pda/app/mob_hunter_game)) - attempt_capture(P) - return 1 + attempt_capture(P, -20) //attempting a melee capture reduces the mob's effective run_chance by 20% to balance the risk of triggering a trap mob + return 1 /obj/effect/nanomob/hitby(obj/item/O) if(invisibility) //no catching mobs you can't normally see! return if(istype(O, /obj/item/device/pda)) var/obj/item/device/pda/P = O - if(P.current_app && istype(P.current_app, /datum/data/pda/app/mob_hunter_game)) - attempt_capture(P) - return 1 + attempt_capture(P) //attempting a ranged capture does not affect the mob's effective run_chance but does prevent you from being shocked by a trap mob + return 1 -/obj/effect/nanomob/proc/attempt_capture(obj/item/device/pda/P) +/obj/effect/nanomob/proc/attempt_capture(obj/item/device/pda/P, catch_mod = 0) //negative catch_mods lower effective run chance, if(!P || !P.current_app || !istype(P.current_app, /datum/data/pda/app/mob_hunter_game) || !P.cartridge) return var/datum/data/pda/app/mob_hunter_game/client = P.current_app + var/total_catch_mod = client.catch_mod + catch_mod //negative values decrease the chance of the mob running, positive values makes it more likely to flee if(!client.connected) //must be connected to attempt captures - for(var/mob/O in hearers(4, P.loc)) - O.show_message("[bicon(P)] No server connection. Capture aborted.") + P.audible_message("[bicon(P)] No server connection. Capture aborted.", null, 4) return if(mob_info.is_trap) //traps work even if you ran into them before, which is why this is before the clients_encountered check @@ -84,16 +82,16 @@ else //deal with the new hunter by either running away or getting caught clients_encountered += cart_ref var/message = "[bicon(P)] " - if(mob_info.run_chance && prob(mob_info.run_chance)) + var/effective_run_chance = mob_info.run_chance + total_catch_mod + if((effective_run_chance > 0) && prob(effective_run_chance)) message += "Capture failed! [name] escaped [P.owner ? "from [P.owner]" : "from this hunter"]!" else - if(client.register_capture(mob_info)) + if(client.register_capture(mob_info, 1)) message += "Capture success! [P.owner ? P.owner : "This hunter"] captured [name]!" else message += "Capture error! Try again." clients_encountered -= cart_ref //if the capture registration failed somehow, let them have another chance with this mob - for(var/mob/O in hearers(4, P.loc)) - O.show_message(message) + P.audible_message(message, null, 4) /obj/effect/nanomob/proc/despawn() if(mob_hunt_server) @@ -107,8 +105,6 @@ /obj/effect/nanomob/proc/reveal() if(invisibility == 101) invisibility = 0 - //density = 1 spawn(30) if(src) invisibility = 101 - //density = 1 diff --git a/code/modules/arcade/mob_hunt/mob_datums.dm b/code/modules/arcade/mob_hunt/mob_datums.dm index 07987594b44..20dd869bf28 100644 --- a/code/modules/arcade/mob_hunt/mob_datums.dm +++ b/code/modules/arcade/mob_hunt/mob_datums.dm @@ -62,6 +62,10 @@ if(prob(1) && prob(1)) is_shiny = 1 health[2] = base_health + (level * health_multiplier) + if(primary_type) + primary_type = new primary_type() + if(secondary_type) + secondary_type = new secondary_type() if(no_register) //for booster pack cards return if(mob_hunt_server) @@ -101,7 +105,9 @@ var/list/possible_areas = list() //setup, sets all station areas (and subtypes) to weight 1 for(var/A in the_station_areas) - if(istype(A, /area/holodeck)) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on z2 as well + if(A == /area/holodeck) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on z2 as well + continue + if(A in possible_areas) continue for(var/areapath in typesof(A)) possible_areas[areapath] = 1 @@ -128,10 +134,16 @@ for(var/A in area_blacklist) for(var/areapath in typesof(A)) possible_areas[areapath] -= 2 - //weight check, remove negative or zero weight areas from the list, then return the list + //removes "bad areas" which shouldn't be on-station but are subtypes of station areas. probably should the unused ones and consider repathing the rest + var/list/bad_areas = list(subtypesof(/area/construction), /area/solar/derelict_starboard, /area/solar/derelict_aft, /area/solar/constructionsite) + for(var/A in bad_areas) + possible_areas -= A + //weight check, remove negative or zero weight areas from the list, then return the list. for(var/areapath in possible_areas) + //remove any areas that shouldn't be on the station-level if(possible_areas[areapath] < 1) possible_areas -= areapath + continue return possible_areas /datum/mob_hunt/proc/get_possible_turfs(area/spawn_area) @@ -140,6 +152,8 @@ var/list/possible_turfs = list() //setup, sets all turfs in spawn_area to weight 1 for(var/turf/T in spawn_area) + if(T.z > 1) //mobs will only consider station-level turfs for spawning. Largely here so we won't have to worry about mapping errors or mobs on the derelict solars + continue possible_turfs[T] = 1 //primary type preferences if(primary_type) @@ -229,13 +243,13 @@ if(!primary_type) return "Typeless" else - return initial(primary_type.name) + return primary_type.name /datum/mob_hunt/proc/get_type2() if(!secondary_type) return null else - return initial(secondary_type.name) + return secondary_type.name /datum/mob_hunt/nemabug diff --git a/code/modules/pda/mob_hunt_game_app.dm b/code/modules/pda/mob_hunt_game_app.dm index 2d034ba13de..512f320a32b 100644 --- a/code/modules/pda/mob_hunt_game_app.dm +++ b/code/modules/pda/mob_hunt_game_app.dm @@ -15,6 +15,8 @@ var/current_index = 0 var/connected = 0 var/hacked = 0 //if set, this cartridge is able to spawn trap mobs from its collection (set via emag_act on the cartridge) + var/catch_mod = 0 //used to adjust the likelihood of a mob running from this client, a negative value means it is less likely to run (support for temporary bonuses) + var/wild_captures = 0 //used to track the total number of mobs captured from the wild (does not count card mobs) by this client /datum/data/pda/app/mob_hunter_game/start() ..() @@ -42,8 +44,7 @@ mob_hunt_server.connected_clients += src connected = 1 if(pda) - for(var/mob/O in hearers(2, pda.loc)) - O.show_message("[bicon(pda)] Connection established. Capture all of the mobs, [pda.owner ? pda.owner : "hunter"]!") + pda.audible_message("[bicon(pda)] Connection established. Capture all of the mobs, [pda.owner ? pda.owner : "hunter"]!", null, 2) return 1 /datum/data/pda/app/mob_hunter_game/proc/disconnect(reason = null) @@ -53,18 +54,25 @@ connected = 0 //show a disconnect message if we were disconnected involuntarily (reason argument provided) if(pda && reason) - for(var/mob/O in hearers(2, pda.loc)) - O.show_message("[bicon(pda)] Disconnected from server. Reason: [reason].") + pda.audible_message("[bicon(pda)] Disconnected from server. Reason: [reason].", null, 2) /datum/data/pda/app/mob_hunter_game/program_process() if(!mob_hunt_server || !connected) return scan_nearby() -/datum/data/pda/app/mob_hunter_game/proc/register_capture(datum/mob_hunt/captured) +/datum/data/pda/app/mob_hunter_game/program_hit_check() + if(!pda) + return + for(var/obj/effect/nanomob/hit_mob in get_turf(pda)) + hit_mob.hitby(pda) + +/datum/data/pda/app/mob_hunter_game/proc/register_capture(datum/mob_hunt/captured, wild = 0) if(!captured) return 0 my_collection.Add(captured) + if(wild) + wild_captures++ return 1 /datum/data/pda/app/mob_hunter_game/update_ui(mob/user as mob, list/data) @@ -72,6 +80,7 @@ data["connected"] = 0 else data["connected"] = 1 + data["wild_captures"] = wild_captures data["no_collection"] = 0 if(!my_collection.len) data["no_collection"] = 1 diff --git a/nano/templates/pda_mob_hunt.tmpl b/nano/templates/pda_mob_hunt.tmpl index 7bdb87bf9e0..dde4ab82a5c 100644 --- a/nano/templates/pda_mob_hunt.tmpl +++ b/nano/templates/pda_mob_hunt.tmpl @@ -32,6 +32,8 @@ Your collection is empty! Go capture some Nano-Mobs! +
+ Wild mobs captured: {{:data.wild_captures}} {{else}}
@@ -59,6 +61,8 @@
+
+ Wild mobs captured: {{:data.wild_captures}}