upports syndicate pai pet from chomp and emag behaviors (#19249)

* upporting syndicate pai pet

* tgui data

* don't emag cards without a pai

* aaugghh

* allow bingle pai, pai counts for lonely

* modular computers

* fix that

* .

* emag

* that'S fine

* pai card as antag tools

* .

* trashcatch

* that

* .

* only show emag chassis if we have a toolkit too

* .

* .

---------

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
Will
2026-03-05 21:53:36 +01:00
committed by GitHub
co-authored by Kashargul
parent cfd9a46036
commit 14e23e07f0
42 changed files with 453 additions and 190 deletions
@@ -13,20 +13,23 @@
get_asset_datum(/datum/asset/spritesheet_batched/pai_icons),
)
/datum/tgui_module/pai_chassis/tgui_static_data()
/datum/tgui_module/pai_chassis/tgui_static_data(mob/user)
var/list/data = ..()
var/list/available_sprites = list()
var/mob/living/silicon/pai/pai_host = host
for(var/key, value in SSpai.get_chassis_list())
var/datum/pai_sprite/current_sprite = value
var/model_type = "def"
if(istype(current_sprite, /datum/pai_sprite/large))
model_type = "big"
if(current_sprite.emagged && (!pai_host.card.emagged || !pai_host.card.has_emag_toolkit))
continue
UNTYPED_LIST_ADD(available_sprites, list("sprite" = current_sprite.name, "belly" = current_sprite.belly_states, "type" = model_type))
data["pai_chassises"] = available_sprites
return data
/datum/tgui_module/pai_chassis/tgui_data()
/datum/tgui_module/pai_chassis/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/mob/living/silicon/pai/pai_host = host
+63 -27
View File
@@ -22,6 +22,8 @@
var/ram = 100 // Used as currency to purchase different abilities
var/list/software = list()
var/userDNA // The DNA string of our assigned user
var/default_pai_card_path = /obj/item/paicard // Used when the pai is spawned directly by mapping or admin
var/obj/item/paicard/card // The card we inhabit
var/obj/item/radio/borg/pai/radio // Our primary radio
var/obj/item/communicator/integrated/communicator // Our integrated communicator.
@@ -106,7 +108,7 @@
card = loc
if(!istype(card))
card = new(src)
card = new default_pai_card_path(src)
card.pai = src
sradio = new(src)
@@ -131,6 +133,7 @@
add_verb(src, /mob/living/proc/dominate_prey)
add_verb(src, /mob/living/proc/set_size)
add_verb(src, /mob/living/proc/shred_limb)
add_verb(src, /mob/living/proc/toggle_trash_catching)
remove_verb(src, /mob/verb/toggle_gun_mode) // Pai doesn't have support for this and shouldn't be able to use guns anyway
@@ -144,6 +147,9 @@
if(M)
M.toff = FALSE
if(chassis_name != PAI_DEFAULT_CHASSIS) // For subtypes that override base chassis( like the syndi pet pai )
internal_set_chassis( SSpai.chassis_data(chassis_name))
/mob/living/silicon/pai/Login()
. = ..()
if(!holo_icon_south)
@@ -218,26 +224,55 @@
/mob/living/silicon/pai/proc/change_chassis(new_chassis)
if(!(new_chassis in SSpai.get_chassis_list()))
new_chassis = PAI_DEFAULT_CHASSIS
var/datum/pai_sprite/chassis_data = SSpai.chassis_data(chassis_name)
if(chassis_data.emagged && !src.card.emagged)
return
chassis_name = new_chassis
// Get icon data setup
if(chassis_data.holo_projector)
internal_set_holoprojection(chassis_data)
else
internal_set_chassis(chassis_data)
/// Rebuild holosprite from character save slot
/mob/living/silicon/pai/proc/internal_set_holoprojection(datum/pai_sprite/chassis_data)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
//We resize ourselves to normal here for a moment to let the vis_height get reset
var/oursize = size_multiplier
resize(1, FALSE, TRUE, TRUE, FALSE)
if(!holo_icon_south)
get_character_icon()
update_icon()
resize(oursize, FALSE, TRUE, TRUE, FALSE) //And then back again now that we're sure the vis_height is correct.
post_chassis_change(chassis_data)
/// Use data from our sprite datum to set icon
/mob/living/silicon/pai/proc/internal_set_chassis(datum/pai_sprite/chassis_data)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
//We resize ourselves to normal here for a moment to let the vis_height get reset
var/oursize = size_multiplier
resize(1, FALSE, TRUE, TRUE, FALSE)
// Get icon data setup
var/datum/pai_sprite/chassis_data = SSpai.chassis_data(chassis_name)
if(chassis_data.holo_projector)
// Rebuild holosprite from character
if(!holo_icon_south)
get_character_icon()
else
// Get data from our sprite datum
icon = chassis_data.sprite_icon
pixel_x = chassis_data.pixel_x
default_pixel_x = pixel_x
pixel_y = chassis_data.pixel_y
default_pixel_y = pixel_y
vis_height = chassis_data.vis_height
icon = chassis_data.sprite_icon
pixel_x = chassis_data.pixel_x
default_pixel_x = pixel_x
pixel_y = chassis_data.pixel_y
default_pixel_y = pixel_y
vis_height = chassis_data.vis_height
update_icon()
resize(oursize, FALSE, TRUE, TRUE, FALSE) //And then back again now that we're sure the vis_height is correct.
post_chassis_change(chassis_data)
/mob/living/silicon/pai/proc/post_chassis_change(datum/pai_sprite/chassis_data)
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
// Drops you if you change to a non-flying chassis
if(chassis_data.flying)
@@ -255,10 +290,6 @@
if(vore_fullness > vore_capacity && vore_selected)
vore_selected.release_all_contents(TRUE)
update_icon()
resize(oursize, FALSE, TRUE, TRUE, FALSE) //And then back again now that we're sure the vis_height is correct.
//////////////////////////////////////////////////////////////////////////////////////////////////
// Click interactions
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -287,9 +318,6 @@
else if (istype(W, /obj/item/card/id) && idaccessible == 0)
to_chat(user, span_notice("[src] is not accepting access modifcations at this time."))
return
//Overriding this will stop a number of headaches down the track.
/mob/living/silicon/pai/attackby(obj/item/W as obj, mob/user as mob)
if(W.force)
visible_message(span_danger("[user.name] attacks [src] with [W]!"))
src.adjustBruteLoss(W.force)
@@ -297,22 +325,26 @@
else
visible_message(span_warning("[user.name] bonks [src] harmlessly with [W]."))
spawn(1)
if(stat != DEAD) close_up()
if(stat != DEAD)
close_up()
return
/mob/living/silicon/pai/attack_hand(mob/user as mob)
if(user.a_intent == I_HELP)
visible_message(span_notice("[user.name] pats [src]."))
else
visible_message(span_danger("[user.name] boops [src] on the head."))
visible_message(span_notice("\The [user] pats \the [src]."))
return
if(user.a_intent == I_DISARM)
visible_message(span_danger("\The [user] boops \the [src] on the head."))
close_up()
return
. = ..()
/mob/living/silicon/pai/UnarmedAttack(atom/A, proximity_flag)
. = ..()
// Some restricted objects to interact with
var/obj/O = A
if(istype(O) && O.allow_pai_interaction(proximity_flag))
if(istype(O) && O.allow_pai_interaction(src, proximity_flag))
O.attack_hand(src)
return
@@ -333,6 +365,10 @@
to_chat(src,span_warning("A firewall prevents you from interfacing with this device!"))
return
if(istype(A,/obj/item/modular_computer))
to_chat(src,span_warning("Anti-tamper locks prevents you from interfacing with this device! You need your master's permission before going online!"))
return
if(!ismob(A) || A == src)
return
@@ -20,6 +20,8 @@
var/icon_y = 32
var/vis_height = 32
var/emagged = FALSE
// PAI sprites
/datum/pai_sprite/drone
name = PAI_DEFAULT_CHASSIS
@@ -155,6 +157,15 @@
sprite_icon_state = "type13"
holo_eyes_icon_state = "type13-eyes"
/datum/pai_sprite/syndi_fox
name = PAI_DEFAULT_EMAGGED_CHASSIS
sprite_icon = 'icons/mob/pai.dmi'
sprite_icon_state = "syndifox"
resting_belly = FALSE
has_eye_sprites = FALSE
belly_states = 0
emagged = TRUE
// Large pai sprites
/datum/pai_sprite/large
pixel_x = -16