mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-18 11:30:35 +01:00
7265630dde
Turned a ton of unmanaged globals into managed globals. Refactored some UT output. Removed some unused things, including vars. Added a test to ensure people don't keep adding new unmanaged vars.
345 lines
11 KiB
Plaintext
345 lines
11 KiB
Plaintext
/datum/trader
|
|
/// The name of the trader in question
|
|
var/name = "unsuspicious trader"
|
|
/// The place that they are trading from
|
|
var/origin = "some place"
|
|
/// Possible names of the trader origin
|
|
var/list/possible_origins
|
|
/// The current disposition of them to us.
|
|
var/disposition = 0
|
|
/// Flags
|
|
var/trade_flags = TRADER_MONEY
|
|
/// If this is set to a language name this will generate a name from the language
|
|
var/name_language
|
|
/// The icon that shows up in the menu @TODO
|
|
var/icon/portrait
|
|
/// List of species that trader will have a bias against (type = variant)
|
|
var/list/species_bias = list() //for silicons (robots), use "Silicon"
|
|
|
|
/// What items they enjoy trading for. Structure is (type = known/unknown)
|
|
var/list/wanted_items = list()
|
|
/// List of all possible wanted items. Structure is (type = mode)
|
|
var/list/possible_wanted_items
|
|
/// List of all possible trading items. Structure is (type = mode)
|
|
var/list/possible_trading_items
|
|
/// What items they are currently trading away.
|
|
var/list/trading_items = list()
|
|
/// Things they will automatically refuse
|
|
var/list/blacklisted_trade_items = list(/mob/living/carbon/human)
|
|
/// Which sector(s) this merchant can show up
|
|
var/list/allowed_space_sectors = list(SECTOR_ROMANOVICH, SECTOR_TAU_CETI, SECTOR_CORP_ZONE, SECTOR_VALLEY_HALE, SECTOR_BADLANDS, SECTOR_TABITI, SECTOR_AEMAQ, SECTOR_SRANDMARR, SECTOR_NRRAHRAHUL,
|
|
SECTOR_GAKAL, SECTOR_UUEOAESA)
|
|
|
|
/// The list of all their replies and messages. Structure is (id = talk)
|
|
var/list/speech = list()
|
|
|
|
/*SPEECH IDS:
|
|
hail_generic When merchants hail a person
|
|
hail_[race] Race specific hails
|
|
hail_deny When merchant denies a hail
|
|
|
|
insult_good When the player insults a merchant while they are on good disposition
|
|
insult_bad When a player insults a merchatn when they are not on good disposition
|
|
complement_accept When the merchant accepts a complement
|
|
complement_deny When the merchant refuses a complement
|
|
|
|
how_much When a merchant tells the player how much something is.
|
|
trade_complete When a trade is made
|
|
trade_refuse When a trade is refused
|
|
|
|
what_want What the person says when they are asked if they want something
|
|
|
|
*/
|
|
/// How much wanted items are multiplied by when traded for
|
|
var/want_multiplier = 2
|
|
/// How far disposition drops on insult
|
|
var/insult_drop = 5
|
|
/// How far compliments increase disposition
|
|
var/compliment_increase = 5
|
|
/// Whether they refuse further communication
|
|
var/refuse_comms = FALSE
|
|
|
|
/// What message gets sent to mobs that get sold.
|
|
var/mob_transfer_message = "You are transported to ORIGIN."
|
|
|
|
/datum/trader/New()
|
|
..()
|
|
if(name_language)
|
|
if(name_language == TRADER_DEFAULT_NAME)
|
|
name = capitalize(pick(GLOB.first_names_female + GLOB.first_names_male)) + " " + capitalize(pick(GLOB.last_names))
|
|
else
|
|
var/datum/language/L = GLOB.all_languages[name_language]
|
|
if(L)
|
|
name = L.get_random_name(pick(MALE,FEMALE))
|
|
if(possible_origins && possible_origins.len)
|
|
origin = pick(possible_origins)
|
|
|
|
for(var/i in 5 to 8)
|
|
add_to_pool(trading_items, possible_trading_items, force = 1)
|
|
add_to_pool(wanted_items, possible_wanted_items, force = 1)
|
|
|
|
//If this hits 0 then they decide to up and leave.
|
|
/datum/trader/proc/tick()
|
|
addtimer(CALLBACK(src, PROC_REF(do_after_tick)), 1)
|
|
return 1
|
|
|
|
/datum/trader/proc/do_after_tick()
|
|
add_to_pool(trading_items, possible_trading_items, 200)
|
|
add_to_pool(wanted_items, possible_wanted_items, 50)
|
|
remove_from_pool(possible_trading_items, 9) //We want the stock to change every so often, so we make it so that they have roughly 10~11 ish items max
|
|
return
|
|
|
|
/datum/trader/proc/remove_from_pool(var/list/pool, var/chance_per_item)
|
|
if(pool && prob(chance_per_item * pool.len))
|
|
var/i = rand(1,pool.len)
|
|
pool[pool[i]] = null
|
|
pool -= pool[i]
|
|
|
|
/// Gets bias from trader
|
|
/datum/trader/proc/get_bias(var/mob/user)
|
|
var/species
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/person = user
|
|
species = person.species.name
|
|
else if (issilicon(user))
|
|
species = "Silicon"
|
|
|
|
if(!species || !species_bias) // No species to be biased against
|
|
return FALSE
|
|
|
|
// Flatten list
|
|
for(var/item in species_bias)
|
|
var/result = species_bias[item]
|
|
if(islist(item))
|
|
if(species in flatten_list(item))
|
|
return result
|
|
else if(species == item)
|
|
return result
|
|
// At this point, species is not on bias list
|
|
return FALSE
|
|
|
|
/datum/trader/proc/add_to_pool(var/list/pool, var/list/possible, var/base_chance = 100, var/force = 0)
|
|
var/divisor = 1
|
|
if(pool && pool.len)
|
|
divisor = pool.len
|
|
if(force || prob(base_chance/divisor))
|
|
var/new_item = get_possible_item(possible)
|
|
if(new_item)
|
|
pool |= new_item
|
|
|
|
/datum/trader/proc/get_possible_item(var/list/trading_pool)
|
|
if(!trading_pool || !trading_pool.len)
|
|
return
|
|
var/list/possible = list()
|
|
for(var/type in trading_pool)
|
|
var/status = trading_pool[type]
|
|
if(status & TRADER_THIS_TYPE)
|
|
possible += type
|
|
if(status & TRADER_SUBTYPES_ONLY)
|
|
possible += subtypesof(type)
|
|
if(status & TRADER_BLACKLIST)
|
|
possible -= type
|
|
if(status & TRADER_BLACKLIST_SUB)
|
|
possible -= subtypesof(type)
|
|
|
|
if(possible.len)
|
|
var/picked = pick(possible)
|
|
var/atom/A = picked
|
|
if(initial(A.name) in list("object", "item","weapon", "structure", "machinery", "exosuit", "organ", "snack")) //weed out a few of the common bad types. Reason we don't check types specifically is that (hopefully) further bad subtypes don't set their name up and are similar.
|
|
return
|
|
return picked
|
|
|
|
/datum/trader/proc/get_response(var/key, var/default)
|
|
var/text
|
|
if(speech && speech[key])
|
|
text = speech[key]
|
|
else
|
|
text = default
|
|
text = replacetext(text, "MERCHANT", name)
|
|
return replacetext(text, "ORIGIN", origin)
|
|
|
|
/datum/trader/proc/print_trading_items(var/num)
|
|
num = clamp(num,1,trading_items.len)
|
|
if(trading_items[num])
|
|
var/atom/movable/M = trading_items[num]
|
|
return "[initial(M.name)]"
|
|
|
|
/datum/trader/proc/get_item_value(var/trading_num, var/mob/user)
|
|
if(!trading_items[trading_items[trading_num]])
|
|
var/type = trading_items[trading_num]
|
|
var/value = get_value(type)
|
|
value = round(rand(80,100)/100 * value) //For some reason rand doesn't like decimals.
|
|
trading_items[type] = value
|
|
// Apply Racism
|
|
// defaults at 1, adjusts based on bias
|
|
var/modifier = 1
|
|
var/bias = get_bias(user)
|
|
if(bias == TRADER_BIAS_UPCHARGE)
|
|
modifier = 1.2 // 20% upcharge
|
|
else if(bias == TRADER_BIAS_DISCOUNT)
|
|
modifier = 0.8 // 20% discount
|
|
return round(trading_items[trading_items[trading_num]] * modifier)
|
|
|
|
/datum/trader/proc/offer_money_for_trade(var/trade_num, var/money_amount, var/mob/user)
|
|
if(!(trade_flags & TRADER_MONEY))
|
|
return TRADER_NO_MONEY
|
|
var/value = get_item_value(trade_num, user)
|
|
if(money_amount < value)
|
|
return TRADER_NOT_ENOUGH
|
|
|
|
return value
|
|
|
|
/datum/trader/proc/offer_items_for_trade(var/list/offers, var/num, var/turf/location, var/mob/user)
|
|
if(!offers || !offers.len)
|
|
return TRADER_NOT_ENOUGH
|
|
num = clamp(num, 1, trading_items.len)
|
|
var/offer_worth = 0
|
|
for(var/item in offers)
|
|
var/atom/movable/offer = item
|
|
var/is_wanted = FALSE
|
|
if(is_type_in_list(offer,wanted_items))
|
|
is_wanted = TRUE
|
|
if(blacklisted_trade_items && blacklisted_trade_items.len)
|
|
if(ishuman(offer))
|
|
var/mob/living/carbon/human/A = offer
|
|
if(is_type_in_list(A.species, blacklisted_trade_items))
|
|
return FALSE
|
|
else if(is_type_in_list(offer,blacklisted_trade_items))
|
|
return FALSE
|
|
|
|
if(istype(offer,/obj/item/spacecash))
|
|
if(!(trade_flags & TRADER_MONEY))
|
|
return TRADER_NO_MONEY
|
|
else
|
|
if(!(trade_flags & TRADER_GOODS))
|
|
return TRADER_NO_GOODS
|
|
else if((trade_flags & TRADER_WANTED_ONLY) && !is_wanted)
|
|
return TRADER_FOUND_UNWANTED
|
|
|
|
offer_worth += get_value(offer) * (is_wanted ? want_multiplier : 1)
|
|
if(!offer_worth)
|
|
return TRADER_NOT_ENOUGH
|
|
var/trading_worth = get_item_value(num, user)
|
|
if(!trading_worth)
|
|
return TRADER_NOT_ENOUGH
|
|
var/percent = offer_worth/trading_worth
|
|
if(percent > max(0.9,0.9-disposition/100))
|
|
return trade(offers, num, location)
|
|
return TRADER_NOT_ENOUGH
|
|
|
|
/datum/trader/proc/hail(var/mob/user)
|
|
// specific subspecies
|
|
var/specific
|
|
// species, used if specific hail not found
|
|
var/general
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
if(H.species)
|
|
var/list/all_lists = list(
|
|
ALL_HUMAN_SPECIES = "Human",
|
|
ALL_DIONA_SPECIES = "Diona",
|
|
ALL_SKRELL_SPECIES = "Skrell",
|
|
ALL_TAJARA_SPECIES = "Tajara",
|
|
ALL_VAURCA_SPECIES = "Vaurca",
|
|
ALL_IPC_SPECIES = "IPC"
|
|
)
|
|
for(var/list/species_list in all_lists)
|
|
if(H.species.name in species_list)
|
|
general = all_lists[species_list]
|
|
break
|
|
// grab subspecies
|
|
specific = H.species.name
|
|
else if(istype(user, /mob/living/silicon))
|
|
specific = "silicon"
|
|
if(!speech["hail_[specific]"])
|
|
//check for generic
|
|
if(speech["hail_[general]"])
|
|
specific = general //we override specific with general to call it
|
|
else
|
|
specific = "generic"
|
|
. = get_response("hail_[specific]", "Greetings, MOB!")
|
|
. = replacetext(., "MOB", user.name)
|
|
|
|
/datum/trader/proc/can_hail(var/mob/user)
|
|
if(!refuse_comms && prob(-disposition))
|
|
refuse_comms = TRUE
|
|
else if(!refuse_comms && get_bias(user) == TRADER_BIAS_DENY)
|
|
refuse_comms = TRUE
|
|
|
|
return !refuse_comms
|
|
|
|
/datum/trader/proc/insult()
|
|
disposition -= rand(insult_drop, insult_drop * 2)
|
|
if(prob(-disposition/10))
|
|
refuse_comms = 1
|
|
if(disposition > 50)
|
|
return get_response("insult_good","What? I thought we were cool!")
|
|
else
|
|
return get_response("insult_bad", "Right back at you asshole!")
|
|
|
|
/datum/trader/proc/compliment()
|
|
if(prob(-disposition))
|
|
return get_response("compliment_deny", "Fuck you!")
|
|
if(prob(100-disposition))
|
|
disposition += rand(compliment_increase, compliment_increase * 2)
|
|
return get_response("compliment_accept", "Thank you!")
|
|
|
|
/datum/trader/proc/trade(var/list/offers, var/num, var/turf/location)
|
|
if(offers && offers.len)
|
|
for(var/offer in offers)
|
|
if(istype(offer,/mob))
|
|
var/text = mob_transfer_message
|
|
to_chat(offer, replacetext(text, "ORIGIN", origin))
|
|
qdel(offer)
|
|
|
|
var/type = trading_items[num]
|
|
|
|
var/atom/movable/M = new type(location)
|
|
playsound(location, 'sound/effects/teleport.ogg', 50, 1)
|
|
|
|
disposition += rand(compliment_increase,compliment_increase*3) //Traders like it when you trade with them
|
|
|
|
return M
|
|
|
|
/datum/trader/proc/how_much_do_you_want(var/num, var/mob/user)
|
|
var/atom/movable/M = trading_items[num]
|
|
. = get_response("how_much", "Hmm.... how about VALUE credits?")
|
|
. = replacetext(.,"VALUE",get_item_value(num, user))
|
|
. = replacetext(.,"ITEM", initial(M.name))
|
|
|
|
/datum/trader/proc/what_do_you_want()
|
|
if(!(trade_flags & TRADER_GOODS))
|
|
return get_response(TRADER_NO_GOODS, "I don't deal in goods.")
|
|
|
|
. = get_response("what_want", "Hm, I want")
|
|
var/list/want_english = list()
|
|
for(var/type in wanted_items)
|
|
var/atom/a = type
|
|
want_english += initial(a.name)
|
|
. += " [english_list(want_english)]"
|
|
|
|
/datum/trader/proc/sell_items(var/list/offers)
|
|
if(!(trade_flags & TRADER_GOODS))
|
|
return TRADER_NO_GOODS
|
|
if(!offers || !offers.len)
|
|
return TRADER_NOT_ENOUGH
|
|
|
|
for(var/offer in offers)
|
|
if(!is_type_in_list(offer,wanted_items))
|
|
return TRADER_FOUND_UNWANTED
|
|
|
|
playsound(get_turf(offers[1]), 'sound/effects/teleport.ogg', 50, 1)
|
|
. = 0
|
|
for(var/offer in offers)
|
|
. += get_value(offer) * want_multiplier
|
|
qdel(offer)
|
|
|
|
/datum/trader/proc/bribe_to_stay_longer(var/amt)
|
|
return get_response("bribe_refusal", "How about... no?")
|
|
|
|
/datum/trader/proc/system_allowed()
|
|
if(SSatlas.current_sector.name in allowed_space_sectors)
|
|
return TRUE
|
|
else
|
|
return FALSE
|