Componentizes armaments (#12515)

* aaaa

* fix
This commit is contained in:
Zonespace
2022-04-03 15:30:07 +01:00
committed by GitHub
parent 2ab308eff1
commit 194176c2a2
3 changed files with 212 additions and 170 deletions
@@ -1,7 +1,7 @@
/**
* This is the componentised version of the armaments vendor.
* This is the component that runs the armaments vendor.
*
* It's intended to be used with NPC vendors, or atoms that otherwise aren't vending machines.
* It's intended to be used with the armament vendor, or other atoms that otherwise aren't vending machines.
*/
/datum/component/armament
@@ -11,8 +11,14 @@
var/list/required_access
/// Our parent machine.
var/atom/parent_atom
/// The points card that is currently inserted into the parent.
var/obj/item/armament_points_card/inserted_card
/// Used to keep track of what categories have been used.
var/list/used_categories = list()
/// Used to keep track of what items have been purchased.
var/list/purchased_items = list()
/datum/component/armament/Initialize(list/required_products, list/required_access)
/datum/component/armament/Initialize(list/required_products, list/needed_access)
if(!required_products)
stack_trace("No products specified for armament")
return COMPONENT_INCOMPATIBLE
@@ -24,9 +30,31 @@
products = required_products
required_access = needed_access
RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
/datum/component/armament/Destroy(force, silent)
if(inserted_card)
inserted_card.forceMove(parent_atom.drop_location())
inserted_card = null
return ..()
/datum/component/armament/proc/on_attackby(atom/target, obj/item, mob/user)
SIGNAL_HANDLER
if(!user || !item)
return
if(!user.can_interact_with(parent_atom))
return
if(!istype(item, /obj/item/armament_points_card))
return
item.forceMove(parent_atom)
inserted_card = item
/datum/component/armament/proc/on_attack_hand(datum/source, mob/living/user)
SIGNAL_HANDLER
@@ -37,6 +65,10 @@
if(!user.can_interact_with(parent_atom))
return
if(!check_access(user))
to_chat(user, span_warning("You don't have the required access!"))
return
INVOKE_ASYNC(src, .proc/ui_interact, user)
/datum/component/armament/ui_interact(mob/user, datum/tgui/ui)
@@ -45,5 +77,172 @@
ui = new(user, src, "ArmamentStation")
ui.open()
/datum/component/armament/ui_data(mob/user)
var/list/data = list()
data["card_inserted"] = inserted_card ? TRUE : FALSE
data["card_name"] = "unknown"
data["card_points"] = 0
if(inserted_card)
data["card_points"] = inserted_card.points
data["card_name"] = inserted_card.name
data["armaments_list"] = list()
for(var/armament_category as anything in GLOB.armament_entries)
var/list/armament_subcategories = list()
for(var/subcategory as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY])
var/list/subcategory_items = list()
for(var/datum/armament_entry/armament_entry as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY][subcategory])
if(products && !(armament_entry.type in products))
continue
subcategory_items += list(list(
"ref" = REF(armament_entry),
"icon" = armament_entry.cached_base64,
"name" = armament_entry.name,
"cost" = armament_entry.cost,
"buyable_ammo" = armament_entry.magazine ? TRUE : FALSE,
"magazine_cost" = armament_entry.magazine_cost,
"quantity" = armament_entry.max_purchase,
"purchased" = purchased_items[armament_entry] ? purchased_items[armament_entry] : 0,
"description" = armament_entry.description,
"armament_category" = armament_entry.category,
"equipment_subcategory" = armament_entry.subcategory,
))
if(!LAZYLEN(subcategory_items))
continue
armament_subcategories += list(list(
"subcategory" = subcategory,
"items" = subcategory_items,
))
if(!LAZYLEN(armament_subcategories))
continue
data["armaments_list"] += list(list(
"category" = armament_category,
"category_limit" = GLOB.armament_entries[armament_category][CATEGORY_LIMIT],
"category_uses" = used_categories[armament_category],
"subcategories" = armament_subcategories,
))
return data
/datum/component/armament/ui_act(action, list/params)
. = ..()
if(.)
return
switch(action)
if("equip_item")
var/check = check_item(params["armament_ref"])
if(!check)
return
select_armament(usr, check)
if("buy_ammo")
var/check = check_item(params["armament_ref"])
if(!check)
return
buy_ammo(usr, check, params["quantity"])
if("eject_card")
eject_card(usr)
/datum/component/armament/proc/buy_ammo(mob/user, datum/armament_entry/armament_entry, quantity = 1)
if(!armament_entry.magazine)
return
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
var/quantity_cost = armament_entry.magazine_cost * quantity
if(!inserted_card.use_points(quantity_cost))
to_chat(user, span_warning("Not enough points!"))
return
for(var/i in 1 to quantity)
new armament_entry.magazine(parent_atom.drop_location())
/datum/component/armament/proc/check_item(reference)
var/datum/armament_entry/armament_entry
for(var/category in GLOB.armament_entries)
for(var/subcategory in GLOB.armament_entries[category][CATEGORY_ENTRY])
armament_entry = locate(reference) in GLOB.armament_entries[category][CATEGORY_ENTRY][subcategory]
if(armament_entry)
break
if(armament_entry)
break
if(!armament_entry)
return FALSE
if(products && !(armament_entry.type in products))
return FALSE
return armament_entry
/datum/component/armament/proc/eject_card(mob/user)
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
inserted_card.forceMove(parent_atom.drop_location())
user.put_in_hands(inserted_card)
inserted_card = null
to_chat(user, span_notice("Card ejected!"))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70)
/datum/component/armament/proc/select_armament(mob/user, datum/armament_entry/armament_entry)
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
if(used_categories[armament_entry.category] >= GLOB.armament_entries[armament_entry.category][CATEGORY_LIMIT])
to_chat(user, span_warning("Category limit reached!"))
return
if(purchased_items[armament_entry] >= armament_entry.max_purchase)
to_chat(user, span_warning("Item limit reached!"))
return
if(!ishuman(user))
return
if(!inserted_card.use_points(armament_entry.cost))
to_chat(user, span_warning("Not enough points!"))
return
var/mob/living/carbon/human/human_to_equip = user
var/obj/item/new_item = new armament_entry.item_type(parent_atom.drop_location())
used_categories[armament_entry.category]++
purchased_items[armament_entry]++
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
if(armament_entry.equip_to_human(human_to_equip, new_item))
to_chat(user, span_notice("Equipped directly to your person."))
playsound(src, 'sound/items/equip/toolbelt_equip.ogg', 100)
armament_entry.after_equip(parent_atom.drop_location(), new_item)
/datum/component/armament/proc/check_access(mob/living/user)
if(!user)
return FALSE
if(!required_access)
return TRUE
if(issilicon(user))
if(ispAI(user))
return FALSE
return TRUE //AI can do whatever it wants
if(isAdminGhostAI(user))
return TRUE
//If the mob has the simple_access component with the requried access, the check passes
else if(SEND_SIGNAL(user, COMSIG_MOB_TRIED_ACCESS, src) & ACCESS_ALLOWED)
return TRUE
//If the mob is holding a valid ID, they pass the access check
else if(check_access(user.get_active_held_item()))
return TRUE
//if they are wearing a card that has access and are human, that works
else if(ishuman(user))
var/mob/living/carbon/human/human_user = user
if(check_access(human_user.wear_id))
return TRUE
//if they're strange and have a hacky ID card as an animal
else if(isanimal(user))
var/mob/living/simple_animal/animal = user
if(check_access(animal.access_card))
return TRUE
@@ -2,7 +2,7 @@
* Armament Station
*
* These are the stations designed to be used by players to outfit themselves.
* They contain a "products" variable which you can populate with your own set of armament entries.
* They are a container for the armament component, which must be supplied with a type path of armament entries, and optionally a list of required accesses to use the vendor.
*
* If you plan on making your own station, it is strongly recommended you use your own armament entries for whatever it is you're doing.
*
@@ -10,176 +10,23 @@
*
* @author Gandalf2k15
*/
/obj/machinery/armament_station
name = "Armament Outfitting Station"
desc = "A versatile station for equipping your weapons."
icon = 'icons/obj/vending.dmi'
icon_state = "liberationstation"
density = TRUE
/// Used to keep track of what categories have been used
var/list/used_categories = list()
/// Used to keep track of what items have been purchased
var/list/purchased_items = list()
/// If set, will limit this station to the products within this list.
var/list/products
/// The points card that is currently inserted.
var/obj/item/armament_points_card/inserted_card
/// The armament entry type path that will fill the armament station's list.
var/armament_type
/// The access needed to use the vendor
var/list/required_access = list()
/obj/machinery/armament_station/attackby(obj/item/weapon, mob/user, params)
/obj/machinery/armament_station/ComponentInitialize()
. = ..()
if(istype(weapon, /obj/item/armament_points_card))
var/obj/item/inserting_card = weapon
if(inserted_card)
to_chat(user, span_warning("There is already a card inserted into [src]!"))
return
inserted_card = inserting_card
inserted_card.forceMove(src)
to_chat(user, span_notice("You insert [inserting_card] into [src]!"))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70)
/obj/machinery/armament_station/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ArmamentStation")
ui.open()
// This data proc may look complex. That's because it is.
/obj/machinery/armament_station/ui_data(mob/user)
var/list/data = list()
data["card_inserted"] = inserted_card ? TRUE : FALSE
data["card_name"] = "unknown"
data["card_points"] = 0
if(inserted_card)
data["card_points"] = inserted_card.points
data["card_name"] = inserted_card.name
data["armaments_list"] = list()
for(var/armament_category as anything in GLOB.armament_entries)
var/list/armament_subcategories = list()
for(var/subcategory as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY])
var/list/subcategory_items = list()
for(var/datum/armament_entry/armament_entry as anything in GLOB.armament_entries[armament_category][CATEGORY_ENTRY][subcategory])
if(products && !(armament_entry.type in products))
continue
subcategory_items += list(list(
"ref" = REF(armament_entry),
"icon" = armament_entry.cached_base64,
"name" = armament_entry.name,
"cost" = armament_entry.cost,
"buyable_ammo" = armament_entry.magazine ? TRUE : FALSE,
"magazine_cost" = armament_entry.magazine_cost,
"quantity" = armament_entry.max_purchase,
"purchased" = purchased_items[armament_entry] ? purchased_items[armament_entry] : 0,
"description" = armament_entry.description,
"armament_category" = armament_entry.category,
"equipment_subcategory" = armament_entry.subcategory,
))
if(!LAZYLEN(subcategory_items))
continue
armament_subcategories += list(list(
"subcategory" = subcategory,
"items" = subcategory_items,
))
if(!LAZYLEN(armament_subcategories))
continue
data["armaments_list"] += list(list(
"category" = armament_category,
"category_limit" = GLOB.armament_entries[armament_category][CATEGORY_LIMIT],
"category_uses" = used_categories[armament_category],
"subcategories" = armament_subcategories,
))
return data
/obj/machinery/armament_station/ui_act(action, list/params)
. = ..()
if(.)
if(!armament_type)
return
AddComponent(/datum/component/armament, subtypesof(armament_type), ACCESS_SYNDICATE)
switch(action)
if("equip_item")
var/check = check_item(params["armament_ref"])
if(!check)
return
select_armament(usr, check)
if("buy_ammo")
var/check = check_item(params["armament_ref"])
if(!check)
return
buy_ammo(usr, check, params["quantity"])
if("eject_card")
eject_card(usr)
/obj/machinery/armament_station/proc/buy_ammo(mob/user, datum/armament_entry/armament_entry, quantity = 1)
if(!armament_entry.magazine)
return
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
var/quantity_cost = armament_entry.magazine_cost * quantity
if(!inserted_card.use_points(quantity_cost))
to_chat(user, span_warning("Not enough points!"))
return
for(var/i in 1 to quantity)
new armament_entry.magazine(drop_location())
/obj/machinery/armament_station/proc/check_item(reference)
var/datum/armament_entry/armament_entry
for(var/category in GLOB.armament_entries)
for(var/subcategory in GLOB.armament_entries[category][CATEGORY_ENTRY])
armament_entry = locate(reference) in GLOB.armament_entries[category][CATEGORY_ENTRY][subcategory]
if(armament_entry)
break
if(armament_entry)
break
if(!armament_entry)
return FALSE
if(products && !(armament_entry.type in products))
return FALSE
return armament_entry
/obj/machinery/armament_station/proc/eject_card(mob/user)
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
inserted_card.forceMove(drop_location())
user.put_in_hands(inserted_card)
inserted_card = null
to_chat(user, span_notice("Card ejected!"))
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 70)
/obj/machinery/armament_station/proc/select_armament(mob/user, datum/armament_entry/armament_entry)
if(!inserted_card)
to_chat(user, span_warning("No card inserted!"))
return
if(used_categories[armament_entry.category] >= GLOB.armament_entries[armament_entry.category][CATEGORY_LIMIT])
to_chat(user, span_warning("Category limit reached!"))
return
if(purchased_items[armament_entry] >= armament_entry.max_purchase)
to_chat(user, span_warning("Item limit reached!"))
return
if(!ishuman(user))
return
if(!inserted_card.use_points(armament_entry.cost))
to_chat(user, span_warning("Not enough points!"))
return
var/mob/living/carbon/human/human_to_equip = user
var/obj/item/new_item = new armament_entry.item_type(drop_location())
used_categories[armament_entry.category]++
purchased_items[armament_entry]++
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
if(armament_entry.equip_to_human(human_to_equip, new_item))
to_chat(user, span_notice("Equipped directly to your person."))
playsound(src, 'sound/items/equip/toolbelt_equip.ogg', 100)
armament_entry.after_equip(drop_location(), new_item)
/**
* Armament points card
@@ -2,13 +2,9 @@
/obj/machinery/armament_station/assault_operatives
name = "Military Grade Armament Station"
req_access = list(ACCESS_SYNDICATE)
/obj/machinery/armament_station/assault_operatives/Initialize(mapload)
. = ..()
products = subtypesof(/datum/armament_entry/assault_operatives)
required_access = list(ACCESS_SYNDICATE)
armament_type = /datum/armament_entry/assault_operatives
// POINTS CARDS
/obj/item/armament_points_card/assaultops