mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-29 06:58:30 +01:00
Issue #4 - Porting resize (micro/macro) systems.
* Instead of "playerscale" we are using pre-existing variable "size_multiplier" but we move it to /mob/living * Added basic mechanics of size changing. * Mousetraps snap small people even if they have shoes. * Big people can walk over small people, or stomp them, or capture them in foot slot. * Ported holder for micros, making small people scoopable. * Tied held micros in with the vore code so they are edible. * Ported size-altering reagents and recipies. * Ported size gun along with associated sprites and sounds.
This commit is contained in:
@@ -65,7 +65,7 @@
|
||||
//Things we can eat with vore code
|
||||
var/list/vore_items = list(
|
||||
/obj/item/weapon/grab,
|
||||
/obj/item/weapon/holder)
|
||||
/obj/item/weapon/holder/micro)
|
||||
|
||||
if(!(I.type in vore_items))
|
||||
return 0
|
||||
@@ -106,11 +106,19 @@
|
||||
else
|
||||
log_debug("[attacker] attempted to feed [G.affecting] to [src] ([src.type]) but it failed.")
|
||||
|
||||
|
||||
//Handle case: /obj/item/weapon/holder
|
||||
if(/obj/item/weapon/holder)
|
||||
return 1
|
||||
if(/obj/item/weapon/holder/micro)
|
||||
var/obj/item/weapon/holder/H = I
|
||||
|
||||
if(!isliving(user)) return 0 // Return 0 to continue upper procs
|
||||
var/mob/living/attacker = user // Typecast to living
|
||||
|
||||
if (is_vore_predator(src))
|
||||
for (var/mob/living/M in H.contents)
|
||||
attacker.eat_held_mob(attacker, M, src)
|
||||
return 1 //Return 1 to exit upper procs
|
||||
else
|
||||
log_debug("[attacker] attempted to feed [H.contents] to [src] ([src.type]) but it is not predator-capable")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Gravity Pull effect which draws in movable objects to its center.
|
||||
// In this case, "number" refers to the range. directions is ignored.
|
||||
//
|
||||
/datum/effect/effect/system/grav_pull
|
||||
var/pull_radius = 3
|
||||
var/pull_anchored = 0
|
||||
var/break_windows = 0
|
||||
|
||||
/datum/effect/effect/system/grav_pull/set_up(range, num, loca)
|
||||
pull_radius = range
|
||||
number = num
|
||||
if(istype(loca, /turf/))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
|
||||
/datum/effect/effect/system/grav_pull/start()
|
||||
spawn(0)
|
||||
if(holder)
|
||||
src.location = get_turf(holder)
|
||||
for(var/i=0, i < number, i++)
|
||||
do_pull()
|
||||
sleep(25)
|
||||
|
||||
/datum/effect/effect/system/grav_pull/proc/do_pull()
|
||||
//following is adapted from supermatter and singulo code
|
||||
if(defer_powernet_rebuild != 2)
|
||||
defer_powernet_rebuild = 1
|
||||
|
||||
// Let's just make this one loop.
|
||||
for(var/atom/X in orange(pull_radius, location))
|
||||
// Movable atoms only
|
||||
if(istype(X, /atom/movable))
|
||||
if(istype(X, /obj/effect/overlay)) continue
|
||||
if(X && !istype(X, /mob/living/carbon/human))
|
||||
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
|
||||
var/obj/structure/window/W = X
|
||||
W.ex_act(2.0)
|
||||
|
||||
if(istype(X, /obj))
|
||||
var/obj/O = X
|
||||
if(O.anchored)
|
||||
if (!pull_anchored) continue // Don't pull anchored stuff unless configured
|
||||
step_towards(X, location) // step just once if anchored
|
||||
continue
|
||||
|
||||
step_towards(X, location) // Step twice
|
||||
step_towards(X, location)
|
||||
|
||||
else if(istype(X,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = X
|
||||
if(istype(H.shoes,/obj/item/clothing/shoes/magboots))
|
||||
var/obj/item/clothing/shoes/magboots/M = H.shoes
|
||||
if(M.magpulse)
|
||||
step_towards(H, location) //step just once with magboots
|
||||
continue
|
||||
step_towards(H, location) //step twice
|
||||
step_towards(H, location)
|
||||
|
||||
if(defer_powernet_rebuild != 2)
|
||||
defer_powernet_rebuild = 0
|
||||
return
|
||||
@@ -0,0 +1,33 @@
|
||||
// Micro Holders - Extends /obj/item/weapon/holder
|
||||
|
||||
/obj/item/weapon/holder/micro
|
||||
name = "micro"
|
||||
desc = "Another crewmember, small enough to fit in your hand."
|
||||
icon_state = "micro"
|
||||
slot_flags = SLOT_FEET | SLOT_HEAD | SLOT_ID
|
||||
w_class = 2
|
||||
item_icons = null // Override value from parent. We don't have magic sprites.
|
||||
pixel_y = 0 // Override value from parent.
|
||||
|
||||
/obj/item/weapon/holder/micro/examine(var/mob/user)
|
||||
for(var/mob/living/M in contents)
|
||||
M.examine(user)
|
||||
|
||||
/obj/item/weapon/holder/MouseDrop(mob/M as mob)
|
||||
..()
|
||||
if(M != usr) return
|
||||
if(usr == src) return
|
||||
if(!Adjacent(usr)) return
|
||||
if(istype(M,/mob/living/silicon/ai)) return
|
||||
for(var/mob/living/carbon/human/O in contents)
|
||||
O.show_inv(usr)
|
||||
|
||||
/obj/item/weapon/holder/micro/attack_self(var/mob/living/user)
|
||||
for(var/mob/living/carbon/human/M in contents)
|
||||
M.help_shake_act(user)
|
||||
|
||||
/obj/item/weapon/holder/micro/update_state()
|
||||
// If any items have been dropped by contained mob, drop them to floor.
|
||||
for(var/obj/O in contents)
|
||||
O.forceMove(get_turf(src))
|
||||
..()
|
||||
@@ -0,0 +1,191 @@
|
||||
|
||||
//these aren't defines so they can stay in this file
|
||||
var/const/RESIZE_HUGE = 2
|
||||
var/const/RESIZE_BIG = 1.5
|
||||
var/const/RESIZE_NORMAL = 1
|
||||
var/const/RESIZE_SMALL = 0.5
|
||||
var/const/RESIZE_TINY = 0.25
|
||||
|
||||
//average
|
||||
var/const/RESIZE_A_HUGEBIG = (RESIZE_HUGE + RESIZE_BIG) / 2
|
||||
var/const/RESIZE_A_BIGNORMAL = (RESIZE_BIG + RESIZE_NORMAL) / 2
|
||||
var/const/RESIZE_A_NORMALSMALL = (RESIZE_NORMAL + RESIZE_SMALL) / 2
|
||||
var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
|
||||
|
||||
// Adding needed defines to /mob/living
|
||||
// Note: Polaris had this on /mob/living/carbon/human We need it higher up for animals and stuff.
|
||||
/mob/living
|
||||
var/size_multiplier = 1 //multiplier for the mob's icon size
|
||||
|
||||
// Define holder_type on types we want to be scoop-able
|
||||
/mob/living/carbon/human
|
||||
holder_type = /obj/item/weapon/holder/micro
|
||||
|
||||
/**
|
||||
* Scale up the size of a mob's icon by the size_multiplier.
|
||||
* NOTE: mob/living/carbon/human/update_icons() has a more complicated system and
|
||||
* is already applying this transform. BUT, it does not call ..()
|
||||
* as long as that is true, we should be fine. If that changes we need to
|
||||
* re-evaluate.
|
||||
*/
|
||||
/mob/living/update_icons()
|
||||
ASSERT(!ishuman(src))
|
||||
var/matrix/M = matrix()
|
||||
M.Scale(size_multiplier)
|
||||
M.Translate(0, 16*(size_multiplier-1))
|
||||
src.transform = M
|
||||
|
||||
/**
|
||||
* Get the effective size of a mob.
|
||||
* Currently this is based only on size_multiplier for micro/macro stuff,
|
||||
* but in the future we may also incorporate the "mob_size", so that
|
||||
* a macro mouse is still only effectively "normal" or a micro dragon is still large etc.
|
||||
*/
|
||||
/mob/living/proc/get_effective_size()
|
||||
return src.size_multiplier
|
||||
|
||||
/**
|
||||
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
|
||||
* It can be used by anything that calls it.
|
||||
*/
|
||||
/mob/living/proc/resize(var/new_size)
|
||||
var/matrix/resize = matrix() // Defines the matrix to change the player's size
|
||||
resize.Scale(new_size) //Change the size of the matrix
|
||||
|
||||
if(new_size >= RESIZE_NORMAL)
|
||||
resize.Translate(0, -1 * (1 - new_size) * 16) //Move the player up in the tile so their feet align with the bottom
|
||||
|
||||
animate(src, transform = resize, time = 5) //Animate the player resizing
|
||||
size_multiplier = new_size //Change size_multiplier so that other items can interact with them
|
||||
|
||||
/**
|
||||
* Verb proc for a command that lets players change their size OOCly.
|
||||
* Ace was here! Redid this a little so we'd use math for shrinking characters. This is the old code.
|
||||
*/
|
||||
/mob/living/proc/set_size()
|
||||
set name = "Set Character Size"
|
||||
set category = "Vore"
|
||||
var/nagmessage = "DO NOT ABUSE THESE COMMANDS. They are not here for you to play with. \
|
||||
We were originally going to remove them but kept them for popular demand. \
|
||||
Do not abuse their existence outside of ERP scenes where they apply, \
|
||||
or reverting OOCly unwanted changes like someone lolshooting the crew with a shrink ray. -Ace"
|
||||
|
||||
var/size_name = input(nagmessage, "Pick a Size") in player_sizes_list
|
||||
if (size_name && player_sizes_list[size_name])
|
||||
src.resize(player_sizes_list[size_name])
|
||||
message_admins("[key_name(src)] used the resize command in-game to be [size_name]. \
|
||||
([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
|
||||
|
||||
/** Add the set_size() proc to usable verbs. */
|
||||
/hook/living_new/proc/resize_setup(mob/living/M)
|
||||
M.verbs += /mob/living/proc/set_size
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Attempt to scoop up this mob up into M's hands, if the size difference is large enough.
|
||||
* @return false if normal code should continue, 1 to prevent normal code.
|
||||
*/
|
||||
/mob/living/proc/attempt_to_scoop(var/mob/living/carbon/human/M)
|
||||
if(!istype(M))
|
||||
return 0;
|
||||
if(M.get_effective_size() - src.get_effective_size() >= 0.75)
|
||||
var/obj/item/weapon/holder/m_holder = get_scooped(M)
|
||||
if (m_holder)
|
||||
return 1
|
||||
else
|
||||
return 0; // Unable to scoop, let other code run
|
||||
|
||||
/**
|
||||
* Handle bumping into someone with helping intent.
|
||||
* Called from /mob/living/Bump() in the 'brohugs all around' section.
|
||||
* @return false if normal code should continue, 1 to prevent normal code.
|
||||
* // TODO - can the now_pushing = 0 be moved up? What does it do anyway?
|
||||
*/
|
||||
/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
|
||||
if(src.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
|
||||
// Both small! Go ahead and
|
||||
now_pushing = 0
|
||||
return 1
|
||||
if(abs(src.get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
if(src.get_effective_size() > tmob.get_effective_size())
|
||||
var/mob/living/carbon/human/M = src
|
||||
if(0) // POLARISTODO istaur(src) && M.taur_style == 2)
|
||||
src << "You carefully slither around [tmob]."
|
||||
tmob << "[src]'s huge tail slithers past beside you!"
|
||||
else
|
||||
src << "You carefully step over [tmob]."
|
||||
tmob << "[src] steps over you carefully!"
|
||||
if(tmob.get_effective_size() > src.get_effective_size())
|
||||
var/mob/living/carbon/human/M = tmob
|
||||
if(0) // POLARISTODO istaur(src) && M.taur == 2)
|
||||
src << "You jump over [tmob]'s thick tail."
|
||||
tmob << "[src] bounds over your tail."
|
||||
else
|
||||
src << "You run between [tmob]'s legs."
|
||||
tmob << "[src] runs between your legs."
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Handle bumping into someone without mutual help intent.
|
||||
* Called from /mob/living/Bump()
|
||||
* NW was here, adding even more options for stomping!
|
||||
*
|
||||
* @return false if normal code should continue, 1 to prevent normal code.
|
||||
*/
|
||||
/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
|
||||
ASSERT(istype(tmob)) // Baby don't hurt me
|
||||
|
||||
if(src.a_intent == I_DISARM && src.canmove && !src.buckled)
|
||||
// If bigger than them by at least 0.75, move onto them and print message.
|
||||
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
src.forceMove(tmob.loc)
|
||||
tmob.Stun(4)
|
||||
|
||||
var/mob/living/carbon/human/M = src
|
||||
if(0) // POLARISTODO istaur(src) && M.taur_style == 2)
|
||||
src << "You carefully squish [tmob] under your tail!"
|
||||
tmob << "[src] pins you under their tail!"
|
||||
else
|
||||
src << "You pin [tmob] beneath your foot!"
|
||||
tmob << "[src] pins you beneath their foot!"
|
||||
return 1
|
||||
|
||||
if(src.a_intent == I_HURT && src.canmove && !src.buckled)
|
||||
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
src.forceMove(tmob.loc)
|
||||
tmob.apply_damage(10, HALLOSS)
|
||||
|
||||
var/mob/living/carbon/human/M = src
|
||||
if(0) // POLARISTODO istaur(src) && M.taur_style == 2)
|
||||
src << "You steamroller over [tmob] with your heavy tail!"
|
||||
tmob << "[src] ploughs you down mercilessly with their heavy tail!"
|
||||
else
|
||||
src << "You bring your foot down heavily upon [tmob]!"
|
||||
tmob << "[src] steps carelessly on your body!"
|
||||
return 1
|
||||
|
||||
if(src.a_intent == I_GRAB && src.canmove && !src.buckled)
|
||||
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.75)
|
||||
now_pushing = 0
|
||||
src.forceMove(tmob.loc)
|
||||
|
||||
var/mob/living/carbon/human/M = src
|
||||
if(istype(M) && !M.shoes)
|
||||
// User is a human (capable of scooping) and not wearing shoes! Scoop into foot slot!
|
||||
equip_to_slot_if_possible(tmob.get_scooped(M), slot_shoes, 0, 1)
|
||||
if(0) // POLARISTODO M.taur == 2)
|
||||
src << "You wrap up [tmob] with your powerful tail!"
|
||||
tmob << "[src] binds you with their powerful tail!"
|
||||
else
|
||||
src << "You clench your toes around [tmob]'s body!"
|
||||
tmob << "[src] grabs your body with their toes!"
|
||||
else if(0) // POLARISTODO istaur(src) && M.taur_style == 2)
|
||||
src << "You carefully squish [tmob] under your tail!"
|
||||
tmob << "[src] pins you under their tail!"
|
||||
else
|
||||
src << "You pin [tmob] beneath your foot!"
|
||||
tmob << "[src] pins you beneath their foot!"
|
||||
return 1
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Size Gun
|
||||
//
|
||||
|
||||
/obj/item/weapon/gun/energy/sizegun
|
||||
name = "shrink ray"
|
||||
desc = "A highly advanced ray gun with two settings: Shrink and Grow. Warning: Do not insert into mouth."
|
||||
icon = 'icons/obj/gun_vr.dmi'
|
||||
icon_state = "sizegun-shrink100" // Someone can probably do better. -Ace
|
||||
item_state = null //so the human update icon uses the icon_state instead
|
||||
fire_sound = 'sound/weapons/wave.ogg'
|
||||
charge_cost = 100
|
||||
projectile_type = /obj/item/projectile/beam/shrinklaser
|
||||
origin_tech = "redspace=1;bluespace=4"
|
||||
modifystate = "sizegun-shrink"
|
||||
self_recharge = 1
|
||||
firemodes = list(
|
||||
list(mode_name = "grow",
|
||||
projectile_type = /obj/item/projectile/beam/growlaser,
|
||||
modifystate = "sizegun-grow",
|
||||
fire_sound = 'sound/weapons/pulse3.ogg'
|
||||
),
|
||||
list(mode_name = "shrink",
|
||||
projectile_type = /obj/item/projectile/beam/shrinklaser,
|
||||
modifystate = "sizegun-shrink",
|
||||
fire_sound = 'sound/weapons/wave.ogg'
|
||||
))
|
||||
|
||||
//
|
||||
// Beams for size gun
|
||||
//
|
||||
|
||||
/obj/item/projectile/beam/shrinklaser
|
||||
name = "shrink beam"
|
||||
icon_state = "laser"
|
||||
nodamage = 1
|
||||
damage = 0
|
||||
check_armour = "laser"
|
||||
|
||||
/obj/item/projectile/beam/shrinklaser/on_hit(var/atom/target, var/blocked = 0)
|
||||
if(istype(target, /mob/living))
|
||||
var/mob/living/M = target
|
||||
switch(M.size_multiplier)
|
||||
if(RESIZE_HUGE to INFINITY)
|
||||
M.resize(RESIZE_BIG)
|
||||
if(RESIZE_BIG to RESIZE_HUGE)
|
||||
M.resize(RESIZE_NORMAL)
|
||||
if(RESIZE_NORMAL to RESIZE_BIG)
|
||||
M.resize(RESIZE_SMALL)
|
||||
if((0 - INFINITY) to RESIZE_NORMAL)
|
||||
M.resize(RESIZE_TINY)
|
||||
M.update_icons()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/projectile/beam/growlaser
|
||||
name = "growth beam"
|
||||
icon_state = "bluelaser"
|
||||
nodamage = 1
|
||||
damage = 0
|
||||
check_armour = "laser"
|
||||
|
||||
/obj/item/projectile/beam/growlaser/on_hit(var/atom/target, var/blocked = 0)
|
||||
if(istype(target, /mob/living))
|
||||
var/mob/living/M = target
|
||||
switch(M.size_multiplier)
|
||||
if(RESIZE_BIG to RESIZE_HUGE)
|
||||
M.resize(RESIZE_HUGE)
|
||||
if(RESIZE_NORMAL to RESIZE_BIG)
|
||||
M.resize(RESIZE_BIG)
|
||||
if(RESIZE_SMALL to RESIZE_NORMAL)
|
||||
M.resize(RESIZE_NORMAL)
|
||||
if((0 - INFINITY) to RESIZE_TINY)
|
||||
M.resize(RESIZE_SMALL)
|
||||
M.update_icons()
|
||||
return 1
|
||||
Reference in New Issue
Block a user