Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions code/controllers/subsystem/movement/movement_types.dm
Original file line number Diff line number Diff line change
Expand Up @@ -701,17 +701,18 @@
* Arguments:
* moving - The atom we want to move
* directions - A list of acceptable directions to try and move in. Defaults to GLOB.alldirs
* areas - Whitelist of areas allowed by reference, if null, will not use a bounding system
* delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
* timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
* subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
* priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
/datum/controller/subsystem/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info)
/datum/controller/subsystem/move_manager/proc/move_rand(moving, directions, areas, delay, timeout, subsystem, priority, flags, datum/extra_info)
if(!directions)
directions = GLOB.alldirs
return add_to_loop(moving, subsystem, /datum/move_loop/move_rand, priority, flags, extra_info, delay, timeout, directions)
return add_to_loop(moving, subsystem, /datum/move_loop/move_rand, priority, flags, extra_info, delay, timeout, directions, areas)

/**
* This isn't actually the same as walk_rand
Expand All @@ -722,12 +723,14 @@
**/
/datum/move_loop/move_rand
var/list/potential_directions
var/list/areaBounds // grem added a boundary system

/datum/move_loop/move_rand/setup(delay, timeout, list/directions)
/datum/move_loop/move_rand/setup(delay, timeout, list/directions, list/areas)
. = ..()
if(!.)
return
potential_directions = directions
areaBounds = areas

/datum/move_loop/move_rand/compare_loops(datum/move_loop/loop_type, priority, flags, extra_info, delay, timeout, list/directions)
if(..() && (length(potential_directions | directions) == length(potential_directions))) //i guess this could be useful if actually it really has yet to move
Expand All @@ -739,6 +742,12 @@
while(potential_dirs.len)
var/testdir = pick(potential_dirs)
var/turf/moving_towards = get_step(moving, testdir)

if(LAZYLEN(areaBounds)) // test within bounds
if(!(get_area(moving_towards) in areaBounds))
potential_dirs -= testdir
continue

var/atom/old_loc = moving.loc
moving.Move(moving_towards, testdir)
if(old_loc != moving?.loc) //If it worked, we're done
Expand Down
Binary file modified config/title_screens/images/house.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions fortune13.dme
Original file line number Diff line number Diff line change
Expand Up @@ -3968,6 +3968,8 @@
#include "modular_coyote\code\modules\mapping\occupation_removal.dm"
#include "modular_coyote\code\modules\mapping\turf_patches.dm"
#include "modular_coyote\code\modules\mapping\wren_billboards.dm"
#include "modular_coyote\code\modules\mob\npc_dialogue.dm"
#include "modular_coyote\code\modules\mob\simple_traders.dm"
#include "modular_coyote\code\modules\mob\dead\new_player\sprite_accessories\body_markings.dm"
#include "modular_coyote\code\modules\regeneration\_defines\signals_statuseffects.dm"
#include "modular_coyote\code\modules\regeneration\sleepingpart\regenerate_sleeping.dm"
Expand Down
205 changes: 205 additions & 0 deletions modular_coyote/code/modules/mob/npc_dialogue.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/datum/component/npc_ui
var/range = 2 // how many tiles can you click on the NPC?
var/ui_ref = "NPCDialogue"

// /datum/component/npc_ui/Initialize()
// if(!ismob(parent))
// return COMPONENT_INCOMPATIBLE

// . = ..()

/datum/component/npc_ui/RegisterWithParent()
. = ..()
RegisterSignal(parent, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW), PROC_REF(on_attack_hand))

/datum/component/npc_ui/UnregisterFromParent()
. = ..()
UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW))

/datum/component/npc_ui/proc/on_attack_hand(datum/source, mob/user)
SIGNAL_HANDLER
var/mob/M = user
var/mob/parentM = parent

if(parentM.stat != CONSCIOUS)
return

if(M)
if(M.get_active_held_item() || M.a_intent != INTENT_HELP)
return // Do not open UI under these conditions

. = COMPONENT_NO_ATTACK

INVOKE_ASYNC(src, PROC_REF(present_ui), user)


/datum/component/npc_ui/trader
ui_ref = "NPCTrading"

var/product_records = list()

///Default price of items if not overridden
var/default_price = PRICE_NORMAL

var/force_free

var/vend_ready

var/stored_caps = 0
var/icon_vend


/datum/component/npc_ui/proc/present_ui(mob/user, datum/tgui/ui)
var/atom/A = parent
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, parent, ui_ref, A.name)
ui.open()


/datum/component/npc_ui/trader/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/vending),
)

/datum/component/npc_ui/trader/ui_static_data(mob/user)
. = list()
// .["onstation"] = onstation
// .["department"] = payment_department
.["product_records"] = list()
for (var/datum/data/vending_product/R in product_records)
var/list/data = list(
asset = get_spritesheet_icon_key_from_type(R.product_path),
name = R.name,
price = R.custom_price || default_price,
max_amount = R.max_amount,
ref = REF(R)
)
.["product_records"] += list(data)
// .["coin_records"] = list()
// for (var/datum/data/vending_product/R in coin_records)
// var/list/data = list(
// asset = get_spritesheet_icon_key_from_type(R.product_path),
// name = R.name,
// price = R.custom_premium_price || extra_price,
// max_amount = R.max_amount,
// ref = REF(R),
// premium = TRUE
// )
// .["coin_records"] += list(data)
// .["hidden_records"] = list()
// for (var/datum/data/vending_product/R in hidden_records)
// var/list/data = list(
// asset = get_spritesheet_icon_key_from_type(R.product_path),
// name = R.name,
// price = R.custom_premium_price || extra_price, //may cause breakage. please note
// max_amount = R.max_amount,
// ref = REF(R),
// premium = TRUE
// )
// .["hidden_records"] += list(data)

/datum/component/npc_ui/trader/ui_data(mob/user)
. = list()
var/mob/living/carbon/human/H
var/obj/item/card/id/C
if(ishuman(user))
H = user
C = H.get_idcard()
if(C?.registered_account)
.["user"] = list()
.["user"]["name"] = C.registered_account.account_holder
.["user"]["cash"] = C.registered_account.account_balance
.["stock"] = list()
for (var/datum/data/vending_product/R in product_records)
.["stock"][R.name] = R.amount
// .["extended_inventory"] = extended_inventory
.["insertedCoins"] = stored_caps ? stored_caps : "0"
.["forceFree"] = force_free


/datum/component/npc_ui/trader/ui_act(action,params)
. = ..()
if(.)
return
switch(action)
if("vend")
. = TRUE
if(!vend_ready)
return
vend_ready = FALSE //One thing at a time!!
var/datum/data/vending_product/R = locate(params["ref"])
var/list/record_to_check = product_records // + coin_records
// if(extended_inventory)
// record_to_check = product_records + coin_records + hidden_records
if(!R || !istype(R) || !R.product_path)
vend_ready = TRUE
return

//debug
// Not needed cause we don't need this :3
// if(product_records.Find(R) && hidden_records.Find(R))
// log_runtime("WARN - vendor [src] @ [loc] has Duplicate [R] accross normal and hidden product tables!")
// if(product_records.Find(R) && coin_records.Find(R))
// log_runtime("WARN - vendor [src] @ [loc] has Duplicate [R] accross normal and premium product tables!")

//Set price for the item we're using.
var/price_to_use = default_price
if(R.custom_price)
price_to_use = R.custom_price
// if(coin_records.Find(R) || hidden_records.Find(R))
// price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price

//Make sure we actually have the item.
// if(R in hidden_records)
// if(!extended_inventory)
// vend_ready = TRUE
// return
if (!(R in record_to_check))
vend_ready = TRUE
message_admins("Vending machine exploit attempted by [ADMIN_LOOKUPFLW(usr)]!")
return
if (R.amount <= 0)
//say("Sold out of [R.name].")
//flick(icon_deny,src)
// parent.say(pick(locale["sold_out"]))
vend_ready = TRUE
return

//Thank them like any megaglobal corp should.
// if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
// say("Thank you for shopping with [src]!")
// purchase_message_cooldown = world.time + 5 SECONDS
// last_shopper = REF(usr)

//Do we have the money inserted to buy this item?
if(price_to_use > stored_caps && !force_free)
to_chat(usr, span_alert("Not enough coins to pay for [R.name]!"))
vend_ready = TRUE
return

//Deduct that price if we're not overridden to be free.
if(!force_free)
stored_caps = stored_caps - price_to_use

//use power, play animations and sounds.
if(icon_vend) //Show the vending animation if needed
flick(icon_vend,src)
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) // lmao keeping this in for now

// TODO: Make NPC fetch and retrieve the item from the inventory.

//Set up what we're vending and actually vend it to the person buying it.
var/obj/item/vended = new R.product_path(get_turf(parent))
R.amount--

// if(usr.can_reach(src) && usr.put_in_hands(vended))
// to_chat(usr, span_notice("You take [R.name] out of the slot."))
// else
// to_chat(usr, span_warning("[capitalize(R.name)] falls onto the floor!"))

SSblackbox.record_feedback("nested tally", "vending_machine_usage", 1, list("[type]", "[R.product_path]"))
vend_ready = TRUE

if("ejectCaps")
//remove_all_caps()
Loading
Loading