mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-01-07 08:02:49 +00:00
Two new terminals have been added just outside the holodeck, capable to projecting holograms of your Nano-Mobs for you to pit in battle against your rival (or your other Nano-Mobs). Battling is turn-based, with each side choosing to either attack, recall, or surrender (if they don't have a mob on the field). Reducing your rival's Nano-Mob to 0 health will down it, earning your mob valuable battle experience and even increasing it's level! Surrendering ends the battle, but does not grant experience as the battle was not completed. Additionally, Medical has provided a brand new Nano-Mob Hunter GO! Restoration Terminal for use in their lobby area. Simply swipe any Nano-Mob card through and it will be restored to full health instantly!
501 lines
16 KiB
Plaintext
501 lines
16 KiB
Plaintext
|
|
#define TYPE_FIRE /datum/mob_type/fire
|
|
#define TYPE_WATER /datum/mob_type/water
|
|
#define TYPE_GRASS /datum/mob_type/grass
|
|
#define TYPE_ELECTRIC /datum/mob_type/electric
|
|
#define TYPE_GROUND /datum/mob_type/ground
|
|
#define TYPE_ROCK /datum/mob_type/rock
|
|
#define TYPE_BUG /datum/mob_type/bug
|
|
#define TYPE_POISON /datum/mob_type/poison
|
|
#define TYPE_NORMAL /datum/mob_type/normal
|
|
#define TYPE_FIGHTING /datum/mob_type/fighting
|
|
#define TYPE_PSYCHIC /datum/mob_type/psychic
|
|
#define TYPE_GHOST /datum/mob_type/ghost
|
|
#define TYPE_ICE /datum/mob_type/ice
|
|
#define TYPE_FLYING /datum/mob_type/flying
|
|
#define TYPE_BLUESPACE /datum/mob_type/bluespace
|
|
#define TYPE_DARK /datum/mob_type/dark
|
|
#define TYPE_STEEL /datum/mob_type/steel
|
|
|
|
/datum/mob_hunt
|
|
//GENERAL STATS AND VARIABLES
|
|
var/mob_name = "Generic Mob" //the mob's original name (its species/type/whatever)
|
|
var/nickname = "" //the mob's nickname (if given by the owner)
|
|
var/run_chance = 0 //percent chance the mob will escape capture attempts (higher is obviously more likely to get away)
|
|
|
|
//COMBAT STATS AND VARIABLES
|
|
var/level = 0 //actual level of this mob (don't set this, it gets overwritten in New())
|
|
var/min_level = 1 //minimum level of this mob (used for randomizing the actual level)
|
|
var/max_level = 1 //maximum level of this mob (used for randomizing the actual level)
|
|
var/exp = 0 //number of battles the mob has won towards the next level (resets to 0 on level-up)
|
|
var/exp_to_level = 3 //number of battles the mob must win to level up (in case we want to make some mobs harder or easier to level)
|
|
//the types of the mob will be used for battles to determine damage resistance or weakness (mob_type_datums.dm)
|
|
var/datum/mob_type/primary_type //Make sure you set this or the mob will be unable to deal damage and will take absurd damage in battles
|
|
var/datum/mob_type/secondary_type //Don't set if not a dual-type mob so the mob will only calculate damage based on primary type
|
|
var/base_attack = 5 //base damage dealt by the mob's attacks for battling (effectively damage dealt at level 0)
|
|
var/base_health = 5 //base health of the mob for battling (effectively max health at level 0)
|
|
var/attack_multiplier = 1 //how much additional damage per level the mob deals (level * attack_multiplier)
|
|
var/health_multiplier = 1 //how much additional health per level the mob gets (level * health_multiplier) for calculating max health
|
|
var/cur_health = 0
|
|
var/max_health = 0
|
|
|
|
//SPAWN PREFERENCES AND VARIABLES
|
|
//A note on mob spawn preferences: The mob types also have preferences, which are handled prior to per-mob preferences, so ultimately you use a combined set of preferences
|
|
var/list/area_blacklist = list() //list of areas this mob can NOT spawn in (such as the bridge)
|
|
var/list/turf_blacklist = list() //list of turfs this mob can NOT spawn on (such as wood floors)
|
|
var/list/area_whitelist = list() //list of areas this mob is more likely to spawn in (can be used to reinclude subtypes of blacklisted areas)
|
|
var/list/turf_whitelist = list() //list of turfs this mob is more likely to spawn on (can be used to reinclude subtypes of blacklisted turfs)
|
|
var/turf/spawn_point //gets set and sent to the game server to spawn its avatar (generated in select_spawn or assigned via set_trap)
|
|
var/lifetime = 6000 //number of deciseconds the mob will remain before despawning (REMEMBER: DECISECONDS! So 6000 is 600 seconds which is 10 minutes)
|
|
var/is_shiny = 0 //if this gets set at spawn (super rare), the mob is considered "shiny" and will use the shiny icon_state and holographic cards
|
|
|
|
//the icon file for mob_hunt stuff is 'icons/effects/mob_hunt.dmi' so reference that for the following vars
|
|
var/icon_state_normal = "placeholder" //the icon_state for this mob's normal version
|
|
var/icon_state_shiny = "placeholder" //the icon_state for this mob's rare shiney version
|
|
|
|
var/is_trap = 0 //if this gets set, the mob is a booby-trap and will electrocute any players that dare attempt to catch it
|
|
|
|
/datum/mob_hunt/New(set_trap = 0, turf/trap_turf = null, no_register = 0)
|
|
if(set_trap)
|
|
level = max_level
|
|
is_trap = 1
|
|
spawn_point = trap_turf
|
|
else
|
|
level = rand(min_level, max_level)
|
|
if(prob(1) && prob(1))
|
|
is_shiny = 1
|
|
max_health = base_health + (level * health_multiplier)
|
|
cur_health = max_health
|
|
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)
|
|
if(set_trap)
|
|
if(mob_hunt_server.register_trap(src))
|
|
return
|
|
else if(select_spawn())
|
|
if(mob_hunt_server.register_spawn(src))
|
|
return
|
|
qdel(src) //if you reach this, the datum is just pure clutter, so delete it
|
|
|
|
/datum/mob_hunt/proc/select_spawn()
|
|
var/list/possible_areas = get_possible_areas()
|
|
if(!possible_areas.len)
|
|
log_admin("No possible areas to spawn [type] found. Possible code/mapping error?")
|
|
return 0
|
|
while(possible_areas.len)
|
|
//randomly select an area from our possible_areas list to try spawning in, then remove it from possible_areas so it won't get picked over and over forever.
|
|
var/area/spawn_area = locate(pickweight(possible_areas))
|
|
possible_areas -= spawn_area
|
|
if(!spawn_area)
|
|
break
|
|
//clear and generate a fresh list of turfs in the selected area, weighted based on white/black lists
|
|
var/list/possible_turfs = get_possible_turfs(spawn_area)
|
|
if(!possible_turfs.len) //If we don't have any possible turfs, this attempt was a failure. Try again.
|
|
continue
|
|
//if we got this far, we're spawning on this attempt, hooray!
|
|
spawn_point = pickweight(possible_turfs)
|
|
break
|
|
if(!spawn_point)
|
|
//if we get to this, we failed every attempt to find a suitable turf for EVERY area in our list of possible areas. DAMN.
|
|
log_admin("No acceptable turfs to spawn [type] on could be located. Possible code/mapping error, or someone replaced/destroyed all the acceptable turf types?")
|
|
return 0
|
|
return 1
|
|
|
|
/datum/mob_hunt/proc/get_possible_areas()
|
|
var/list/possible_areas = list()
|
|
//setup, sets all station areas (and subtypes) to weight 1
|
|
for(var/A in the_station_areas)
|
|
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
|
|
//primary type preferences
|
|
if(primary_type)
|
|
for(var/A in primary_type.area_whitelist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] += 4
|
|
for(var/A in primary_type.area_blacklist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] -= 2
|
|
//secondary type preferences
|
|
if(secondary_type)
|
|
for(var/A in secondary_type.area_whitelist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] += 4
|
|
for(var/A in secondary_type.area_blacklist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] -= 2
|
|
//mob preferences
|
|
for(var/A in area_whitelist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] += 4
|
|
for(var/A in area_blacklist)
|
|
for(var/areapath in typesof(A))
|
|
possible_areas[areapath] -= 2
|
|
//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)
|
|
if(!spawn_area)
|
|
return list()
|
|
var/list/possible_turfs = list()
|
|
//setup, sets all turfs in spawn_area to weight 1
|
|
for(var/turf/T in spawn_area)
|
|
if(!is_station_level(T.z)) //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)
|
|
if(is_type_in_list(T, primary_type.turf_whitelist))
|
|
possible_turfs[T] += 4
|
|
if(is_type_in_list(T, primary_type.turf_blacklist))
|
|
possible_turfs[T] -= 2
|
|
//secondary type preferences
|
|
if(secondary_type)
|
|
if(is_type_in_list(T, secondary_type.turf_whitelist))
|
|
possible_turfs[T] += 4
|
|
if(is_type_in_list(T, secondary_type.turf_blacklist))
|
|
possible_turfs[T] -= 2
|
|
//mob preferences
|
|
if(is_type_in_list(T, turf_whitelist))
|
|
possible_turfs[T] += 4
|
|
if(is_type_in_list(T, turf_blacklist))
|
|
possible_turfs[T] -= 2
|
|
//weight check, remove negative or zero weight turfs from the list, then return the list
|
|
if(possible_turfs[T] < 1)
|
|
possible_turfs -= T
|
|
return possible_turfs
|
|
|
|
/datum/mob_hunt/proc/calc_def_multiplier(datum/mob_type/attack_type)
|
|
if(!primary_type)
|
|
return 99 //typeless mobs are weak to everything since they shouldn't exist
|
|
if(!attack_type) //typeless attacks will return a multiplier of 1 in case we want to use this for calculating unmodified damage for some reason (UI maybe?)
|
|
return 1
|
|
|
|
var/multiplier = 1
|
|
if(attack_type in primary_type.immunity)
|
|
return 0 //a single immunity negates all damage
|
|
else if(attack_type in primary_type.resistance)
|
|
multiplier *= 0.5
|
|
else if(attack_type in primary_type.weakness)
|
|
multiplier *= 2
|
|
else
|
|
multiplier *= 1
|
|
|
|
if(!secondary_type) //if we don't have a second type, we're done here
|
|
return multiplier
|
|
if(attack_type in secondary_type.immunity)
|
|
return 0 //a single immunity negates all damage
|
|
else if(attack_type in secondary_type.resistance)
|
|
multiplier *= 0.5
|
|
else if(attack_type in secondary_type.weakness)
|
|
multiplier *= 2
|
|
else
|
|
multiplier *= 1
|
|
return multiplier
|
|
|
|
/datum/mob_hunt/proc/take_damage(raw_damage, datum/mob_type/attack_type)
|
|
var/message = ""
|
|
var/multiplier = calc_def_multiplier(attack_type)
|
|
var/total_damage = raw_damage * multiplier
|
|
if(!cur_health) //it's already downed, quit hitting it
|
|
return null
|
|
if(!total_damage)
|
|
message += "The attack is completely ineffective! "
|
|
else
|
|
cur_health = max(cur_health - total_damage, 0)
|
|
switch(multiplier)
|
|
if(0)
|
|
message += "The attack is completely ineffective! "
|
|
if(0.25)
|
|
message += "It's barely effective... "
|
|
if(0.5)
|
|
message += "It's not very effective... "
|
|
if(2)
|
|
message += "It's super effective! "
|
|
if(4)
|
|
message += "It's ultra effective! "
|
|
if(99)
|
|
message += pick("REKT! ", "DUNKED! ", "DEFENSE BREAK! ", "WOMBO-COMBO'D!")
|
|
if(!cur_health)
|
|
message += "[nickname ? nickname : mob_name] is downed!"
|
|
return message
|
|
|
|
/datum/mob_hunt/proc/get_raw_damage()
|
|
return (level * attack_multiplier)
|
|
|
|
/datum/mob_hunt/proc/get_attack_type()
|
|
var/datum/mob_type/attack_type = primary_type
|
|
if(secondary_type && prob(40))
|
|
attack_type = secondary_type
|
|
return attack_type
|
|
|
|
/datum/mob_hunt/proc/gain_exp()
|
|
exp++
|
|
var/message = "[nickname ? nickname : mob_name] gained EXP! ([exp] / [exp_to_level] EXP)"
|
|
if(exp >= exp_to_level)
|
|
message = levelup()
|
|
return message
|
|
|
|
/datum/mob_hunt/proc/levelup()
|
|
var/message = ""
|
|
level++
|
|
exp = 0
|
|
if(level > max_level) //This is where we would trigger an evolution, when those are added (need to add evolved forms first)
|
|
level = max_level //for now though, we'll just cap them back at their max_level
|
|
message += "[nickname ? nickname : mob_name] can't get any stronger right now!"
|
|
else
|
|
max_health = base_health + (level * health_multiplier)
|
|
cur_health = max_health //full heal on level-up
|
|
message += "[nickname ? nickname : mob_name] has reached level [level]!"
|
|
return message
|
|
|
|
/datum/mob_hunt/proc/get_type1()
|
|
if(!primary_type)
|
|
return "Typeless"
|
|
else
|
|
return primary_type.name
|
|
|
|
/datum/mob_hunt/proc/get_type2()
|
|
if(!secondary_type)
|
|
return null
|
|
else
|
|
return secondary_type.name
|
|
|
|
|
|
/datum/mob_hunt/nemabug
|
|
mob_name = "Nemabug"
|
|
run_chance = 50
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_BUG
|
|
icon_state_normal = "nemabug"
|
|
icon_state_shiny = "nemabug_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/stoutquill
|
|
mob_name = "Stoutquill"
|
|
run_chance = 50
|
|
min_level = 5
|
|
max_level = 15
|
|
primary_type = TYPE_ICE
|
|
icon_state_normal = "stoutquill"
|
|
icon_state_shiny = "stoutquill_shiny"
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/spectra
|
|
mob_name = "Spectra"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_POISON
|
|
icon_state_normal = "spectra"
|
|
icon_state_shiny = "spectra_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/dunny
|
|
mob_name = "Dunny"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_FIRE
|
|
icon_state_normal = "dunny"
|
|
icon_state_shiny = "dunny_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/buffsel
|
|
mob_name = "Buffsel"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_ROCK
|
|
icon_state_normal = "buffsel"
|
|
icon_state_shiny = "buffsel_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/quarrel
|
|
mob_name = "Quarrel"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_NORMAL
|
|
icon_state_normal = "quarrel"
|
|
icon_state_shiny = "quarrel_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/vulerrt
|
|
mob_name = "Vulerrt"
|
|
run_chance = 50
|
|
min_level = 5
|
|
max_level = 15
|
|
primary_type = TYPE_DARK
|
|
icon_state_normal = "vulerrt"
|
|
icon_state_shiny = "vulerrt_shiny"
|
|
turf_whitelist = list()
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/strudel
|
|
mob_name = "Strudel"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_ELECTRIC
|
|
icon_state_normal = "strudel"
|
|
icon_state_shiny = "strudel_shiny"
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/folstick
|
|
mob_name = "Folstick"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_WATER
|
|
icon_state_normal = "folstick"
|
|
icon_state_shiny = "folstick_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/glimmerflare
|
|
mob_name = "Glimmerflare"
|
|
run_chance = 50
|
|
min_level = 5
|
|
max_level = 15
|
|
primary_type = TYPE_PSYCHIC
|
|
icon_state_normal = "glimmerflare"
|
|
icon_state_shiny = "glimmerflare_shiny"
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/leecoon
|
|
mob_name = "Leecoon"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_GRASS
|
|
icon_state_normal = "leecoon"
|
|
icon_state_shiny = "leecoon_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/halk
|
|
mob_name = "Halk"
|
|
run_chance = 35
|
|
min_level = 1
|
|
max_level = 10
|
|
primary_type = TYPE_FLYING
|
|
icon_state_normal = "halk"
|
|
icon_state_shiny = "halk_shiny"
|
|
lifetime = 6000
|
|
|
|
/datum/mob_hunt/gooby
|
|
mob_name = "Gooby"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_ELECTRIC
|
|
secondary_type = TYPE_BUG
|
|
icon_state_normal = "gooby"
|
|
icon_state_shiny = "gooby_shiny"
|
|
lifetime = 3000
|
|
|
|
/datum/mob_hunt/pandoom
|
|
mob_name = "Pandoom"
|
|
run_chance = 50
|
|
min_level = 5
|
|
max_level = 15
|
|
primary_type = TYPE_GHOST
|
|
icon_state_normal = "pandoom"
|
|
icon_state_shiny = "pandoom_shiny"
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/relish
|
|
mob_name = "Relish"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_FIRE
|
|
secondary_type = TYPE_GROUND
|
|
icon_state_normal = "relish"
|
|
icon_state_shiny = "relish_shiny"
|
|
lifetime = 3000
|
|
|
|
/datum/mob_hunt/xofine
|
|
mob_name = "Xofine"
|
|
run_chance = 50
|
|
min_level = 5
|
|
max_level = 10
|
|
primary_type = TYPE_FIRE
|
|
secondary_type = TYPE_NORMAL
|
|
icon_state_normal = "xofine"
|
|
icon_state_shiny = "xofine_shiny"
|
|
lifetime = 3000
|
|
|
|
/datum/mob_hunt/gitten
|
|
mob_name = "Gitten"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_WATER
|
|
secondary_type = TYPE_POISON
|
|
icon_state_normal = "gitten"
|
|
icon_state_shiny = "gitten_shiny"
|
|
lifetime = 3000
|
|
|
|
/datum/mob_hunt/nai
|
|
mob_name = "Nai"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_GRASS
|
|
secondary_type = TYPE_NORMAL
|
|
icon_state_normal = "nai"
|
|
icon_state_shiny = "nai_shiny"
|
|
lifetime = 3000
|
|
|
|
/datum/mob_hunt/pyroghast
|
|
mob_name = "Pyroghast"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_FIRE
|
|
secondary_type = TYPE_GHOST
|
|
icon_state_normal = "pyroghast"
|
|
icon_state_shiny = "pyroghast"
|
|
lifetime = 4500
|
|
|
|
/datum/mob_hunt/starslam
|
|
mob_name = "Starslam"
|
|
run_chance = 65
|
|
min_level = 5
|
|
max_level = 20
|
|
primary_type = TYPE_FIGHTING
|
|
secondary_type = TYPE_ICE
|
|
icon_state_normal = "starslam"
|
|
icon_state_shiny = "starslam_shiny"
|
|
lifetime = 2500
|
|
|
|
/datum/mob_hunt/pheron
|
|
mob_name = "Pheron"
|
|
run_chance = 85
|
|
min_level = 10
|
|
max_level = 20
|
|
primary_type = TYPE_BLUESPACE
|
|
icon_state_normal = "pheron"
|
|
icon_state_shiny = "pheron_shiny"
|
|
area_blacklist = list()
|
|
turf_blacklist = list()
|
|
area_whitelist = list()
|
|
turf_whitelist = list()
|
|
lifetime = 2000 |