Files
Aurora.3/code/modules/vehicles/animal.dm
T
94d92803b4 Replaces our lighting system with CM's. (#21465)
Depends on #21458.

Ports https://github.com/cmss13-devs/cmss13/pull/4229, with the original
authors as:

- https://github.com/tgstation/TerraGov-Marine-Corps/pull/1964 for the
lighting controller (A-lexa)
- https://github.com/tgstation/TerraGov-Marine-Corps/pull/4747 and
https://github.com/tgstation/TerraGov-Marine-Corps/pull/7263 for the
lighting (TiviPlus)
- https://github.com/tgstation/tgstation/pull/54520 for the dir lighting
component
- https://github.com/tgstation/tgstation/pull/75018 for the out of
bounds fix in lighting
- https://github.com/tgstation/TerraGov-Marine-Corps/pull/6678 for the
emissives (TiviPlus)

The main driving reason behind this is that current lighting consumes
way too much processing power, especially for things like odysseys/away
sites where a billion light sources are processing/moving at once and
the game slows down to a crawl. Hopefully this improves the situation by
a good margin, but we will need some testmerging to confirm that.
<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/1059ba2b-c0c5-495a-9c76-2d75d0c42bf2"
/>
<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/9704b0f6-4cf6-4dfd-a6cb-5702ad07d677"
/>


- [x] Resolve todos
- [x] Look into open space fuckery (border objects)

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: JohnWildkins <john.wildkins@gmail.com>
2025-11-04 21:27:42 +00:00

324 lines
11 KiB
Plaintext

/obj/vehicle/animal
name = "animal"
desc = "Base type of rideable animals - you shouldn't be seeing this!"
load_item_visible = 1
mob_offset_y = 5
health = 100
maxhealth = 100
fire_dam_coeff = 0.6
brute_dam_coeff = 0.5
dir = SOUTH
anchored = FALSE //so you can drag animals around
///The chance of blocking a projectile aimed at the user. Nothing by default.
var/block_chance = 0
/// Speed on land. Higher is slower.
/// If 0 it can't go on land turfs at all.
var/land_speed = 5
/// Speed if walk intent is on.
/// Should be slower, but does not crash into other bikes or people at this speed.
/// If land speed is 0, still can't go on land turfs at all.
var/land_speed_careful = 6
/// Same as land speed, but for space turfs.
var/space_speed = 0
/// Same as land speed if walk intent is on, but for space turfs.
var/space_speed_careful = 0
var/storage_type = /obj/item/storage/toolbox/bike_storage/saddle
var/obj/item/storage/storage_compartment
organic = TRUE
on = TRUE
var/list/armor_values = list( //some default values that seem about right for an average animal
MELEE = ARMOR_MELEE_MEDIUM,
BULLET = ARMOR_BALLISTIC_MINOR,
BOMB = ARMOR_BOMB_MINOR
)
/obj/vehicle/animal/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "Click-drag yourself onto the animal to climb onto it."
. += "Click-drag it onto yourself to access its mounted storage."
/obj/vehicle/animal/Destroy()
QDEL_NULL(storage_compartment)
return ..()
/obj/vehicle/animal/setup_vehicle()
..()
on = TRUE
set_light(0)
AddOverlays(image(icon, "[icon_state]_overlay", MOB_LAYER + 1))
if(storage_type)
storage_compartment = new storage_type(src)
if(LAZYLEN(armor_values))
AddComponent(/datum/component/armor, armor_values)
/obj/vehicle/animal/load(var/atom/movable/C)
var/mob/living/M = C
if(!istype(C)) return FALSE
if(M.buckled_to || M.restrained() || !Adjacent(M) || !M.Adjacent(src))
return FALSE
return ..(M)
/obj/vehicle/animal/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
if(use_check_and_message(user))
return
if(user == over && ishuman(over))
var/mob/living/carbon/human/H = over
storage_compartment.open(H)
/obj/vehicle/animal/mouse_drop_receive(atom/dropped, mob/user, params)
if(use_check_and_message(user))
return
if(!load(dropped))
to_chat(user, SPAN_WARNING("You were unable to load \the [dropped] onto \the [src]."))
return
/obj/vehicle/animal/attack_hand(var/mob/user as mob)
if(use_check_and_message(user))
return
if(user == load)
unload(load)
to_chat(user, "You unbuckle yourself from \the [src]")
if(user != load && load)
user.visible_message ("[user] starts to unbuckle [load] from \the [src]!")
if(do_after(user, 8 SECONDS, src))
unload(load)
to_chat(user, "You unbuckle [load] from \the [src]")
to_chat(load, "You were unbuckled from \the [src] by [user]")
/obj/vehicle/animal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
var/datum/component/armor/armor_component = GetComponent(/datum/component/armor)
if(buckled && prob((1 - armor_component.get_blocked(hitting_projectile.damage_type, hitting_projectile.damage_flags, hitting_projectile.armor_penetration))*100))
return buckled.bullet_act(arglist(args))
..()
/obj/vehicle/animal/relaymove(mob/living/user, direction)
. = ..()
if(user != load || user.incapacitated())
return
return Move(get_step(src, direction))
/obj/vehicle/animal/proc/check_destination(var/turf/destination)
var/static/list/types = typecacheof(list(/turf/space))
if(is_type_in_typecache(destination,types) || pulledby)
return TRUE
else
return FALSE
/obj/vehicle/animal/Move(var/turf/destination)
var/mob/living/rider = buckled
if(!istype(buckled))
return
var/is_careful = (rider.m_intent != M_RUN)
var/is_on_space = check_destination(destination)
if(is_on_space) //IDK when we will ever need space-flying animals but may as well leave the possibility open
if(!space_speed)
return FALSE
move_delay = (is_careful ? space_speed_careful : space_speed)
else
if(!land_speed)
return FALSE
move_delay = (is_careful ? land_speed_careful : land_speed)
return ..()
/obj/vehicle/animal/Collide(var/atom/movable/AM)
. = ..()
collide_act(AM)
/obj/vehicle/animal/proc/collide_act(var/atom/movable/AM)
var/mob/living/M
if(!buckled)
return
if(istype(buckled, /mob/living))
M = buckled
if(M.m_intent == M_RUN)
if (istype(AM, /obj/vehicle))
M.setMoveCooldown(10)
var/obj/vehicle/V = AM
if(prob(50))
if(V.buckled)
if(ishuman(V.buckled))
var/mob/living/carbon/human/I = V.buckled
I.visible_message(SPAN_DANGER("\The [I] falls off from \the [V]"))
V.unload(I)
I.throw_at(get_edge_target_turf(V.loc, V.loc.dir), 5, 1)
I.apply_effect(2, WEAKEN)
if(prob(25))
if(ishuman(buckled))
var/mob/living/carbon/human/C = buckled
C.visible_message(SPAN_DANGER ("\The [C] falls off from \the [src]!"))
unload(C)
C.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
C.apply_effect(2, WEAKEN)
if(isliving(AM))
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Was rammed by [src]</font>"
M.attack_log += "\[[time_stamp()]\] <span class='warning'>rammed[M.name] ([M.ckey]) rammed [H.name] ([H.ckey]) with the [src].</span>"
msg_admin_attack("[src] crashed into [key_name(H)] at (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[H.x];Y=[H.y];Z=[H.z]'>JMP</a>)" )
src.visible_message(SPAN_DANGER("\The [src] smashes into \the [H]!"))
playsound(src, /singleton/sound_category/swing_hit_sound, 50, 1)
H.apply_damage(20, DAMAGE_BRUTE)
H.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
H.apply_effect(4, WEAKEN)
M.setMoveCooldown(10)
return TRUE
else
var/mob/living/L = AM
src.visible_message(SPAN_DANGER("\The [src] smashes into \the [L]!"))
playsound(src, /singleton/sound_category/swing_hit_sound, 50, 1)
L.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
L.apply_damage(20, DAMAGE_BRUTE)
M.setMoveCooldown(10)
return TRUE
/obj/vehicle/animal/climber
name = "climber"
desc = "A rideable beast of burden, large enough for one adult rider only but perfectly adapted for the rough terrain on Adhomai. This one has a saddle mounted on it."
icon = 'icons/mob/npc/adhomai_48.dmi'
icon_state = "climber_s"
pixel_x = -8
mob_offset_y = 8
land_speed = 2
land_speed_careful = 4
health = 100
storage_type = /obj/item/storage/toolbox/bike_storage/saddle
corpse = /mob/living/simple_animal/climber/saddle
/obj/item/storage/toolbox/bike_storage/saddle
name = "saddle storage"
/obj/item/saddle
name = "saddle"
desc = "A structure used to ride animals."
icon = 'icons/obj/saddle.dmi'
icon_state = "saddle"
w_class = WEIGHT_CLASS_NORMAL
/obj/vehicle/animal/threshbeast
name = "threshbeast"
desc = "Large herbivorous reptiles native to Moghes, the azkrazal or 'threshbeast' is commonly used as a mount, beast of burden, or convenient food source by Unathi. They are highly valued for their speed and strength, capable of running at 30-42 miles per hour at top speed. This one has been fitted with a saddle."
icon = 'icons/mob/npc/moghes_64.dmi'
icon_state = "threshbeast_s"
pixel_x = -15
mob_offset_y = 10
land_speed = 2
land_speed_careful = 4
health = 100
organic = TRUE
storage_type = /obj/item/storage/toolbox/bike_storage/saddle
corpse = /mob/living/simple_animal/threshbeast/saddle
/obj/vehicle/animal/hegeranzi
name = "hegeranzi"
desc = "A large species of herbivorous horned reptiles native to Moghes, the hegeranzi or 'warmount' is commonly used as mount or beast of war by the Unathi. They are highly valued for their speed, aggression, and fearsome horns. This one seems to have been fitted with a saddle."
icon = 'icons/mob/npc/moghes_64.dmi'
icon_state = "warmount_s"
pixel_x = -14
mob_offset_y = 12
on = TRUE
land_speed = 1
land_speed_careful = 4
health = 200
organic = TRUE
storage_type = /obj/item/storage/toolbox/bike_storage/saddle
corpse = /mob/living/simple_animal/hostile/retaliate/hegeranzi/saddle
armor_values = list( //big tough war beast, has some more armor particularly against bullets and melee
MELEE = ARMOR_MELEE_MAJOR,
BULLET = ARMOR_BALLISTIC_MEDIUM,
LASER = ARMOR_LASER_MINOR,
BOMB = ARMOR_BOMB_MINOR
)
/obj/vehicle/animal/warmount/RunOver(mob/living/carbon/human/H)
var/mob/living/M
if(!buckled)
return
if(istype(buckled, /mob/living))
M = buckled
if(M.m_intent == M_RUN)
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Was rammed by [src]</font>"
M.attack_log += "\[[time_stamp()]\] <span class='warning'>rammed[M.name] ([M.ckey]) rammed [H.name] ([H.ckey]) with the [src].</span>"
msg_admin_attack("[src] crashed into [key_name(H)] at (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[H.x];Y=[H.y];Z=[H.z]'>JMP</a>)" )
src.visible_message(SPAN_DANGER("\The [src] charges into \the [H]!"))
playsound(src, 'sound/weapons/pierce.ogg', 50, 1)
H.apply_damage(40, DAMAGE_BRUTE)
if(H.species.mob_size < 16)
playsound(M, 'sound/weapons/push_connect.ogg', 50, 1, -1)
src.visible_message(SPAN_DANGER("\The [src] slams into \the [H], sending them flying!"))
var/turf/target_turf = get_ranged_target_turf(H, M.dir, 4)
H.throw_at(target_turf, 4, 1, src)
H.apply_effect(4, WEAKEN)
/obj/vehicle/animal/warmount/collide_act(atom/movable/AM)
var/mob/living/M
if(!buckled)
return
if(istype(buckled, /mob/living))
M = buckled
if(M.m_intent == M_RUN)
if (istype(AM, /obj/vehicle))
M.setMoveCooldown(10)
var/obj/vehicle/V = AM
if(prob(50))
if(V.buckled)
if(ishuman(V.buckled))
var/mob/living/carbon/human/I = V.buckled
I.visible_message(SPAN_DANGER("\The [I] falls off from \the [V]"))
V.unload(I)
I.throw_at(get_edge_target_turf(V.loc, V.loc.dir), 5, 1)
I.apply_effect(2, WEAKEN)
if(prob(25))
if(ishuman(buckled))
var/mob/living/carbon/human/C = buckled
C.visible_message(SPAN_DANGER ("\The [C] falls off from \the [src]!"))
unload(C)
C.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
C.apply_effect(2, WEAKEN)
if(isliving(AM))
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
M.attack_log += "\[[time_stamp()]\]<font color='orange'> Was rammed by [src]</font>"
M.attack_log += "\[[time_stamp()]\] <span class='warning'>rammed[M.name] ([M.ckey]) rammed [H.name] ([H.ckey]) with the [src].</span>"
msg_admin_attack("[src] crashed into [key_name(H)] at (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[H.x];Y=[H.y];Z=[H.z]'>JMP</a>)" )
src.visible_message(SPAN_DANGER("\The [src] charges into \the [H]!"))
playsound(src, 'sound/weapons/pierce.ogg', 50, 1)
H.apply_damage(40, DAMAGE_BRUTE)
if(H.species.mob_size < 16)
playsound(M, 'sound/weapons/push_connect.ogg', 50, 1, -1)
src.visible_message(SPAN_DANGER("\The [src] slams into \the [H], sending them flying!"))
var/turf/target_turf = get_ranged_target_turf(H, M.dir, 4)
H.throw_at(target_turf, 4, 1, src)
H.apply_effect(4, WEAKEN)
M.setMoveCooldown(10)
return TRUE
else
var/mob/living/L = AM
src.visible_message(SPAN_DANGER("\The [src] smashes into \the [L]!"))
playsound(src, 'sound/weapons/pierce.ogg', 50, 1)
L.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
L.apply_damage(40, DAMAGE_BRUTE)
M.setMoveCooldown(10)
return TRUE