Merge branch 'master' into pr/138

This commit is contained in:
BongaTheProto
2022-01-19 12:51:57 -05:00
36 changed files with 536 additions and 33 deletions

View File

@@ -40,7 +40,7 @@ Take note some columns have been renamed, removed or changed type. Any services
START TRANSACTION;
ALTER TABLE `ban`
DROP COLUMN `rounds`
, CHANGE COLUMN `bantype` `bantype` ENUM('PERMABAN', 'TEMPBAN', 'JOB_PERMABAN', 'JOB_TEMPBAN', 'ADMIN_PERMABAN', 'ADMIN_TEMPBAN') NOT NULL
, CHANGE COLUMN `bantype` `bantype` ENUM('PERMABAN', 'TEMPBAN', 'JOB_PERMABAN', 'JOB_TEMPBAN', 'ADMIN_PERMABAN', 'ADMIN_TEMPBAN', 'PACIFICATION_BAN') NOT NULL
, CHANGE COLUMN `reason` `reason` VARCHAR(2048) NOT NULL
, CHANGE COLUMN `who` `who` VARCHAR(2048) NOT NULL
, CHANGE COLUMN `adminwho` `adminwho` VARCHAR(2048) NOT NULL

View File

@@ -73,7 +73,7 @@ CREATE TABLE `ban` (
`server_ip` INT(10) UNSIGNED NOT NULL,
`server_port` SMALLINT(5) UNSIGNED NOT NULL,
`round_id` INT(11) UNSIGNED NOT NULL,
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN') NOT NULL,
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN','PACIFICATION_BAN') NOT NULL,
`reason` varchar(2048) NOT NULL,
`job` varchar(32) DEFAULT NULL,
`duration` int(11) NOT NULL,

View File

@@ -73,7 +73,7 @@ CREATE TABLE `SS13_ban` (
`server_ip` INT(10) UNSIGNED NOT NULL,
`server_port` SMALLINT(5) UNSIGNED NOT NULL,
`round_id` INT(11) UNSIGNED NOT NULL,
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN') NOT NULL,
`bantype` enum('PERMABAN','TEMPBAN','JOB_PERMABAN','JOB_TEMPBAN','ADMIN_PERMABAN','ADMIN_TEMPBAN','PACIFICATION_BAN') NOT NULL,
`reason` varchar(2048) NOT NULL,
`job` varchar(32) DEFAULT NULL,
`duration` int(11) NOT NULL,

View File

@@ -18,6 +18,7 @@
#define BANTYPE_ADMIN_PERMA 7
#define BANTYPE_ADMIN_TEMP 8
#define BANTYPE_ANY_JOB 9 //used to remove jobbans
#define BANTYPE_PACIFIST 10 //makes a person spawn with pacifist. splurt change.
//Admin Permissions
#define R_BUILDMODE (1<<0)

View File

@@ -148,6 +148,9 @@
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
SEND_SIGNAL(new_character, COMSIG_MOB_ON_NEW_MIND)
//splurt change
INVOKE_ASYNC(GLOBAL_PROC, .proc/_paci_check, new_character, old_character)
//end change
/datum/mind/proc/store_memory(new_text)
if((length_char(memory) + length_char(new_text)) <= MAX_MESSAGE_LEN)

View File

@@ -53,8 +53,9 @@
SCAVENGING_SPAWN_MOUSE = 10,
SCAVENGING_SPAWN_MICE = 5,
SCAVENGING_SPAWN_TOM = 1,
/obj/item/clothing/gloves/color/yellow = 0.5)
unique_loot = list(/obj/item/clothing/gloves/color/yellow = 5, SCAVENGING_SPAWN_TOM = 1)
/obj/item/clothing/gloves/color/yellow = 0.5,
/obj/item/book/granter/crafting_recipe/trash_cannon = 0.1)
unique_loot = list(/obj/item/clothing/gloves/color/yellow = 5, SCAVENGING_SPAWN_TOM = 1, /obj/item/book/granter/crafting_recipe/trash_cannon = 1)
/obj/structure/loot_pile/maint/ComponentInitialize()
var/static/safe_maint_items

View File

@@ -51,6 +51,9 @@
announceinirc = 1
blockselfban = 1
kickbannedckey = 1
if(BANTYPE_PACIFIST)
bantype_str = "PACIFICATION_BAN"
bantype_pass = 1
if( !bantype_pass )
return
if( !istext(reason) )
@@ -167,6 +170,10 @@
if(announceinirc)
send2adminchat("BAN ALERT","[a_key] applied a [bantype_str] on [bankey]")
//splurt edit
if(((bantype_str == "PACIFICATION_BAN") || (job == "pacifist")) && banned_client.mob)
ADD_TRAIT(banned_client.mob, TRAIT_PACIFISM, "pacification ban")
//
if(kickbannedckey)
if(AH)
@@ -208,6 +215,9 @@
if(BANTYPE_ANY_JOB)
bantype_str = "ANYJOB"
bantype_pass = 1
if(BANTYPE_PACIFIST)
bantype_str = "PACIFICATION_BAN"
bantype_pass = 1
if( !bantype_pass )
return
@@ -411,6 +421,7 @@
output += "<option value='[BANTYPE_JOB_TEMP]'>JOB TEMPBAN</option>"
output += "<option value='[BANTYPE_ADMIN_PERMA]'>ADMIN PERMABAN</option>"
output += "<option value='[BANTYPE_ADMIN_TEMP]'>ADMIN TEMPBAN</option>"
output += "<option value='[BANTYPE_PACIFIST]'>PACIFICATION BAN</option>"
output += "</select></td>"
output += "<td><b>Key:</b> <input type='text' name='dbbanaddkey'></td></tr>"
output += "<tr><td><b>IP:</b> <input type='text' name='dbbanaddip'></td>"
@@ -546,6 +557,8 @@
typedesc = "<b>ADMIN PERMABAN</b>"
if("ADMIN_TEMPBAN")
typedesc = "<b>ADMIN TEMPBAN</b><br><font size='2'>([duration] minutes [(unbanned) ? "" : "(<a href=\"byond://?src=[REF(src)];[HrefToken()];dbbanedit=duration;dbbanid=[banid]\">Edit</a>))"]<br>Expires [expiration]</font>"
if("PACIFICATION_BAN")
typedesc = "<b>PACIFICATION BAN</b><br><font size='2'>([duration] minutes [(unbanned) ? "" : "(<a href=\"byond://?src=[REF(src)];[HrefToken()];dbbanedit=duration;dbbanid=[banid]\">Edit</a>))"]<br>Expires [expiration]</font>"
output += "<tr bgcolor='[dcolor]'>"
output += "<td align='center'>[typedesc]</td>"

View File

@@ -103,6 +103,11 @@
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=emote;jobban4=[rm]'>Emoteban</A> | "
if(QDELETED(M) || QDELETED(usr))
return
if(jobban_isbanned(M, "pacifist"))
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=pacifist;jobban4=[rm]'><font color=red>PacifistBan</font></A> | "
else
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=pacifist;jobban4=[rm]'>PacifistBan</A> | "
body += "<A href='?_src_=holder;[HrefToken()];showmessageckey=[M.ckey]'>Notes | Messages | Watchlist</A> "
if(M.client)

View File

@@ -260,6 +260,11 @@
to_chat(usr, "Not enough parameters (Requires ckey, severity, reason and duration).")
return
banjob = null
if(BANTYPE_PACIFIST)
if(!banckey || !banreason || !banduration || !banseverity)
to_chat(usr, "Not enough parameters (Requires ckey, severity, reason and duration).")
return
banjob = null
var/mob/playermob
@@ -1060,7 +1065,7 @@
msg += ", [job]"
create_message("note", M.key, null, "Banned from [msg] - [reason]", null, null, 0, 0, null, 0, severity)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes.</span>")
to_chat(M, "<span class='boldannounce'><BIG>You have been [(msg == ("ooc" || "appearance")) ? "banned" : "jobbanned"] by [usr.client.key] from: [msg].</BIG></span>")
to_chat(M, "<span class='boldannounce'><BIG>You have been [((msg == "ooc") || (msg == "appearance") || (msg == "pacifist")) ? "banned" : "jobbanned"] by [usr.client.key] from: [msg == "pacifist" ? "using violence" : msg].</BIG></span>")
to_chat(M, "<span class='boldannounce'>The reason is: [reason]</span>")
to_chat(M, "<span class='danger'>This jobban will be lifted in [mins] minutes.</span>")
href_list["jobban2"] = 1 // lets it fall through and refresh
@@ -1086,7 +1091,7 @@
msg += ", [job]"
create_message("note", M.key, null, "Banned from [msg] - [reason]", null, null, 0, 0, null, 0, severity)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] banned [key_name_admin(M)] from [msg].</span>")
to_chat(M, "<span class='boldannounce'><BIG>You have been [(msg == ("ooc" || "appearance")) ? "banned" : "jobbanned"] by [usr.client.key] from: [msg].</BIG></span>")
to_chat(M, "<span class='boldannounce'><BIG>You have been [((msg == "ooc") || (msg == "appearance") || (msg == "pacifist")) ? "banned" : "jobbanned"] by [usr.client.key] from: [msg == "pacifist" ? "using violence" : msg].</BIG></span>")
to_chat(M, "<span class='boldannounce'>The reason is: [reason]</span>")
to_chat(M, "<span class='danger'>Jobban can be lifted only upon request.</span>")
href_list["jobban2"] = 1 // lets it fall through and refresh

View File

@@ -111,6 +111,11 @@
if(ckey)
M.ckey = ckey
//splurt change
if(jobban_isbanned(M, "pacifist")) //do you love repeat code? i sure do
to_chat(M, "<span class='cult'>You are pacification banned. Pacifist has been force applied.</span>")
ADD_TRAIT(M, TRAIT_PACIFISM, "pacification ban")
//
if(show_flavour)
var/output_message = "<span class='big bold'>[short_desc]</span>"
if(flavour_text != "")
@@ -251,7 +256,7 @@
H.canloadappearance = TRUE
else
H.canloadappearance = FALSE
//Instant version - use when spawning corpses during runtime
/obj/effect/mob_spawn/human/corpse
roundstart = FALSE

View File

@@ -790,6 +790,11 @@
. = new_character
if(.)
new_character.key = key //Manually transfer the key to log them in
//splurt change
if(jobban_isbanned(new_character, "pacifist"))
to_chat(new_character, "<span class='cult'>You are pacification banned. Pacifist has been force applied.</span>")
ADD_TRAIT(new_character, TRAIT_PACIFISM, "pacification ban")
//
new_character.stop_sound_channel(CHANNEL_LOBBYMUSIC)
new_character = null
qdel(src)

View File

@@ -495,8 +495,17 @@
new_mob.ckey = ckey
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
//splurt changeh
INVOKE_ASYNC(GLOBAL_PROC, .proc/_paci_check, new_mob, src)
//
return TRUE
/proc/_paci_check(mob/new_mob, mob/old_mob)
if(jobban_isbanned(new_mob, "pacifist"))
if(!QDELETED(old_mob))
REMOVE_TRAIT(old_mob, TRAIT_PACIFISM, "pacification ban")
ADD_TRAIT(new_mob, TRAIT_PACIFISM, "pacification ban")
/mob/verb/cancel_camera()
set name = "Cancel Camera View"
set category = "OOC"

View File

@@ -3,3 +3,7 @@
## Eg. If set to 0.5, whoever's being picked up shall be 50% or less the size of their partner or they won't be picked up ##
## Defaults to 0.5 if unset, 0 to disable picking up others as a whole ##
#MAX_PICK_RATIO 0.5
## Multiplier for the points earned on a sex table ##
## Setting it to 0 obviously just makes it generate no points at all. ##
#SEX_TABLE_MULTIPLIER 50

View File

@@ -0,0 +1,4 @@
author: NullFag
delete-after: true
changes:
- rscadd: adds kanon

View File

@@ -0,0 +1,11 @@
author: SandPoot
delete-after: true
changes:
- rscadd: Tier of the research table allows someone to be used more times.
- rscadd: Research table can be used for cargo money.
- rscadd: Hella examination text for the research table, hopefully you won't get
confused anymore, hopefully.
- config: There's a config for the multiplier of the research table, try balancing
it!
- bugfix: Fixed some bugs with the research table.
- tweak: The research table can also be deconstructed!

View File

@@ -0,0 +1,4 @@
author: NullFag
delete-after: true
changes:
- admin: adds paci bans

View File

@@ -150,7 +150,7 @@
if(portal_target && (portal_target?.client?.prefs.toggles & VERB_CONSENT || !portal_target.ckey))
user.visible_message("<span class='lewd'>[user] [message].</span>")
if(!arouse_only_target)
if(M.handle_post_sex(lust_amt, null, null))
if(M.handle_post_sex(lust_amt, null, portal_target))
if(P)
to_chat(portal_target, "<span class='userlove'>You feel a [P.shape] penis of [P.length] inches go deep into your [portalunderwear.targetting] and cum!</span>")
switch(user.zone_selected)
@@ -170,7 +170,7 @@
message = replacetext(message, "[M]", "someone")
message = replacetext(message, "[src]", "your [targeted]")
to_chat(portal_target, "<span class='lewd'>You feel something on your panties, it [message][P ? ", it is a [P.shape] penis of [P.length] inches" : ""].</span>")
if(portal_target.handle_post_sex(lust_amt, null, null))
if(portal_target.handle_post_sex(lust_amt, null, M))
switch(portalunderwear.targetting)
if("vagina")
to_chat(M, "<span class='userlove'>You feel \the [V] squirt over your [target]!</span>")

View File

@@ -12,11 +12,6 @@
/obj/item/clothing/suit/armor/vest/stripper/bikini
name = "bikini armor"
desc = "How is this even supposed to work? It barely covers anything!"
icon = 'modular_sand/icons/obj/clothing/suits.dmi'
icon_state = "armorstripperalt"
item_state = "armorstripperalt"
mob_overlay_icon = 'modular_sand/icons/mob/clothing/suit.dmi' //should link to the binkini now
mutantrace_variation = NONE
armor = list("melee" = 15, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
dog_fashion = null

View File

@@ -2,3 +2,7 @@
config_entry_value = 0.5
min_val = 0
integer = FALSE
/datum/config_entry/number/sex_table_multiplier
config_entry_value = 50
min_val = 0

View File

@@ -11,3 +11,29 @@
tools = list(TOOL_CROWBAR)
subcategory = CAT_MISCELLANEOUS
category = CAT_MISCELLANEOUS
/datum/crafting_recipe/trash_cannon
name = "Trash Cannon"
always_availible = FALSE
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER)
result = /obj/structure/cannon/trash
reqs = list(
/obj/item/melee/skateboard/improvised = 1,
/obj/item/tank/internals/oxygen = 1,
/datum/reagent/drug/maint/tar = 15,
/obj/item/restraints/handcuffs/cable = 1,
/obj/item/storage/toolbox = 1,
)
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/trashball
name = "Trashball"
always_availible = FALSE
result = /obj/item/stack/cannonball/trashball
reqs = list(
/obj/item/stack/sheet = 5,
/datum/reagent/consumable/space_cola = 10,
)
category = CAT_WEAPONRY
subcategory = CAT_AMMO

View File

@@ -1,3 +1,6 @@
#define POINT_TYPE_CARGO "cargo"
#define POINT_TYPE_SCIENCE "science"
/obj/machinery/research_table
name = "Sex Research Rack"
desc = "The rack with silicone padding and plenty of straps for subject restraining.\
@@ -14,33 +17,76 @@
var/self_unbuckle_time = 3 MINUTES
var/static/list/users = list()
var/tier = 1
var/multiplier = 100
var/configured = FALSE
var/point_type = POINT_TYPE_SCIENCE
var/max_repeat_usage = 3
/obj/machinery/research_table/examine(mob/user)
. = ..()
if(!configured)
if(configured)
. += "<span class='notice'>The same person can be used up to [max_repeat_usage * tier] time\s.</span>"
switch(point_type)
if(POINT_TYPE_SCIENCE)
. += "<span class='notice'>The table is set to generate science points.</span>"
else
. += "<span class='notice'>The table is set to generate money for cargo.</span>"
if(!configured && !panel_open)
. += "<span class='notice'>It's not configured yet, you could use a <b>multitool</b> to configure it.</span>"
if(panel_open)
. += "<span class='notice'>The panel is <b>screwed</b> open and you could change generation type with a <b>multitool</b>.</span>"
/obj/machinery/research_table/multitool_act(mob/living/user, obj/item/I)
if(user.a_intent == INTENT_HELP)
if(do_after(user, 5 SECONDS, TRUE, src))
configured = !configured
to_chat(user, "<span class='notice'>The research table is now [configured ? "configured" : "not configured"].</span>")
if(panel_open)
user.visible_message("<span class='notice'>[user] begins changing the generation type on \the [src].</span>", "<span class='notice'>You begin changing the generation type on \the [src].</span>")
if(do_after(user, 5 SECONDS, TRUE, src))
point_type = point_type == POINT_TYPE_SCIENCE ? POINT_TYPE_CARGO : POINT_TYPE_SCIENCE
var/generation_message = null
switch(point_type)
if(POINT_TYPE_SCIENCE)
generation_message = "generate research points for science"
else
generation_message = "generate money for cargo"
user.visible_message("<span class='notice'>[user] finished changing the generation type on \the [src].</span>", "<span class='notice'>You change the generation type on \the [src] to [generation_message].</span>")
else
to_chat(user, "<span class='warning'>You need to stand still and uninterrupted for 5 seconds!</span>")
return STOP_ATTACK_PROC_CHAIN
else
to_chat(user, "<span class='warning'>You need to stand still and uninterrupted for 5 seconds!</span>")
return STOP_ATTACK_PROC_CHAIN
user.visible_message("<span class='notice'>[user] begins reconfiguring \the [src].</span>", "<span class='notice'>You begin reconfiguring \the [src].</span>")
if(do_after(user, 5 SECONDS, TRUE, src))
configured = !configured
user.visible_message("<span class='notice'>[user] finished reconfiguring \the [src].</span>", "<span class='notice'>The research table is now [configured ? "configured" : "not configured"].</span>")
else
to_chat(user, "<span class='warning'>You need to stand still and uninterrupted for 5 seconds!</span>")
return STOP_ATTACK_PROC_CHAIN
. = ..()
/obj/machinery/research_table/screwdriver_act(mob/living/user, obj/item/I)
. = ..()
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I))
return STOP_ATTACK_PROC_CHAIN
/obj/machinery/research_table/crowbar_act(mob/living/user, obj/item/I)
. = ..()
if(default_deconstruction_crowbar(I, FALSE))
return STOP_ATTACK_PROC_CHAIN
/obj/machinery/research_table/MouseDrop_T(mob/living/M, mob/living/user)
if(get_turf(M) != get_turf(src) && Adjacent(M) && Adjacent(user) && user.stat == CONSCIOUS)
var/message = M == user ? "[M] climbs on the [src]." : "[user] puts [M] on the [src]."
var/self_message = M == user ? "You climb on the [src]." : "You put [M] on the [src]."
visible_message(message, self_message)
M.forceMove(get_turf(src))
. = ..()
if(istype(M))
if(get_turf(M) != get_turf(src) && user.stat == CONSCIOUS)
var/message = M == user ? "[M] climbs on the [src]." : "[user] puts [M] on the [src]."
var/self_message = M == user ? "You climb on the [src]." : "You put [M] on the [src]."
visible_message(message, self_message)
M.forceMove(get_turf(src))
. = ..()
if(. && !configured) // Successfully buckled, not configured.
say("Warning, table not configured yet!")
return
/obj/machinery/research_table/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
if(INTERACTING_WITH(buckled_mob, src))
to_chat(user, "<span class='notice'>You're already trying to unbuckle [buckled_mob == user ? "yourself" : buckled_mob]!")
return
if(!handle_unbuckling(buckled_mob, user))
if(buckled_mob == user)
to_chat(user, "<span class='warning'>You fail to unbuckle yourself.</span>")
@@ -79,10 +125,10 @@
if(!istype(buckled_mob))
say("Failed to get any data from the subject, it is not a human.")
return
if(buckled_mob.last_partner == buckled_mob)
if((buckled_mob.last_partner && buckled_mob.last_partner == buckled_mob) || buckled_mob == partner)
say("Failed to get any data from the subject, two are needed for the experiment!")
return
if(users[buckled_mob.name] > 5)
if(users[buckled_mob.name] > (max_repeat_usage * tier))
say("There is already too much data from this subject.")
return
users[buckled_mob.name] += 1
@@ -94,6 +140,20 @@
continue
points_awarded += genital.fluid_rate + genital.size
points_awarded *= tier
points_awarded *= multiplier
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_awarded))
say("Obtained [points_awarded] point\s from the session.")
points_awarded *= CONFIG_GET(number/sex_table_multiplier)
switch(point_type)
if(POINT_TYPE_SCIENCE)
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_awarded))
else
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
D.adjust_money(points_awarded)
if(points_awarded)
var/add_s = points_awarded == 1 ? "" : "s"
say("Obtained [points_awarded] [point_type == POINT_TYPE_SCIENCE ? "point" : "credit"][add_s] from the session.")
else
say("Obtained no [point_type == POINT_TYPE_SCIENCE ? "points" : "credits"] from the session.") // Probably has no genitals at all
playsound(src, 'sound/machines/chime.ogg', 30, 1)
#undef POINT_TYPE_CARGO
#undef POINT_TYPE_SCIENCE

View File

@@ -0,0 +1,14 @@
/obj/item/book/granter/crafting_recipe/trash_cannon
name = "diary of a demoted engineer"
desc = "A lost journal. The engineer seems very deranged about their demotion."
crafting_recipe_types = list(
/datum/crafting_recipe/trash_cannon,
/datum/crafting_recipe/trashball,
)
icon_state = "book1"
oneuse = TRUE
remarks = list("\"I'll show them! I'll build a CANNON!\"", "\"Gunpowder is ideal, but i'll have to improvise...\"", "\"I savor the look on the CE's face when I BLOW down the walls to engineering!\"", "\"If the supermatter gets loose from my rampage, so be it!\"", "\"I'VE GONE COMPLETELY MENTAL!\"")
/obj/item/book/granter/crafting_recipe/trash_cannon/recoil(mob/living/carbon/user)
to_chat(user, span_warning("The book turns to dust in your hands."))
qdel(src)

View File

@@ -0,0 +1,138 @@
///how much projectile damage is lost when using a bad fuel
#define BAD_FUEL_DAMAGE_TAX 20
///extra chance it explodes upon firing
#define BAD_FUEL_EXPLODE_PROBABILTY 10
/obj/structure/cannon
name = "cannon"
desc = "Holemaker Deluxe: A sporty model with a good stop power. Any cannon enthusiast should be expected to start here."
density = TRUE
anchored = TRUE
icon = 'modular_splurt/icons/obj/structures/cannons.dmi'
icon_state = "falconet_patina"
max_integrity = 300
///whether the cannon can be unwrenched from the ground.
var/anchorable_cannon = TRUE
var/obj/item/stack/cannonball/loaded_cannonball = null
var/charge_ignited = FALSE
var/fire_delay = 15
var/charge_size = 15
var/fire_sound = 'modular_splurt/sound/weapons/gun/general/cannon.ogg'
/obj/structure/cannon/Initialize(mapload)
. = ..()
create_reagents(charge_size)
/obj/structure/cannon/examine(mob/user)
. = ..()
. += "<span class='notice'>[src] accepts gunpowder or welding fuel.</span>"
. += "<span class='warning'>Using welding fuel will weaken the force of the projectile fired.</span>"
/obj/structure/cannon/proc/fire()
for(var/mob/shaken_mob in urange(10, src))
if(shaken_mob.stat == CONSCIOUS)
shake_camera(shaken_mob, 3, 1)
playsound(src, fire_sound, 50, TRUE)
flick(icon_state+"_fire", src)
if(loaded_cannonball)
var/obj/item/projectile/fired_projectile = new loaded_cannonball.projectile_type(get_turf(src))
if(reagents.has_reagent(/datum/reagent/fuel, charge_size))
fired_projectile.damage = max(2, fired_projectile.damage - BAD_FUEL_DAMAGE_TAX)
QDEL_NULL(loaded_cannonball)
fired_projectile.firer = src
fired_projectile.fired_from = src
fired_projectile.fire(dir2angle(dir))
reagents.remove_all()
charge_ignited = FALSE
/obj/structure/cannon/attackby(obj/item/used_item, mob/user, params)
if(charge_ignited)
to_chat(user, "<span class='warning'>It's gonna fire!</span>")
return
var/ignition_message = used_item.ignition_effect(src, user)
if(istype(used_item, /obj/item/stack/cannonball))
if(loaded_cannonball)
to_chat(user, "<span class='warning'>[src] is already loaded!</span>")
else
var/obj/item/stack/cannonball/cannoneers_balls = used_item
loaded_cannonball = new cannoneers_balls.type(src, 1)
loaded_cannonball.copy_evidences(cannoneers_balls)
to_chat(user, "<span class='notice'>You load a [cannoneers_balls.singular_name] into \the [src].</span>")
cannoneers_balls.use(1, transfer = TRUE)
return
else if(ignition_message)
if(!reagents.has_reagent(/datum/reagent/blackpowder,charge_size) && !reagents.has_reagent(/datum/reagent/fuel,charge_size))
to_chat(user, "<span class='warning'>[src] needs [reagents.maximum_volume]u of charge!</span>")
return
visible_message(ignition_message)
log_game("Cannon fired by [key_name(user)] in [AREACOORD(src)]")
addtimer(CALLBACK(src, .proc/fire), fire_delay)
charge_ignited = TRUE
return
else if(istype(used_item, /obj/item/reagent_containers))
var/obj/item/reagent_containers/powder_keg = used_item
if(!(powder_keg.reagent_flags & OPENCONTAINER))
return ..()
if(istype(powder_keg, /obj/item/reagent_containers/rag))
return ..()
if(!powder_keg.reagents.total_volume)
to_chat(user, "<span class='warning'>[powder_keg] is empty!</span>")
return
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='warning'[src] is full!</span>")
return
var/has_enough_gunpowder = powder_keg.reagents.has_reagent(/datum/reagent/blackpowder, charge_size)
var/has_enough_alt_fuel = powder_keg.reagents.has_reagent(/datum/reagent/fuel, charge_size)
if(!has_enough_gunpowder && !has_enough_alt_fuel)
to_chat(user, "<span class='warning'>[powder_keg] doesn't have at least 15u of fuel to fill [src]!</span>")
return
if(has_enough_gunpowder)
powder_keg.reagents.trans_id_to(src, /datum/reagent/blackpowder, amount = charge_size)
to_chat(user, "<span class='notice'>You load [src] with gunpowder.</span>")
return
if(has_enough_alt_fuel)
powder_keg.reagents.trans_id_to(src, /datum/reagent/fuel, amount = charge_size)
to_chat(user, "<span class='notice'>You load [src] with welding fuel.</span>")
return
if(anchorable_cannon && used_item.tool_behaviour == TOOL_WRENCH)
if(default_unfasten_wrench(user, used_item, time = 2 SECONDS))
return
..()
/obj/structure/cannon/trash
name = "trash cannon"
desc = "Okay, sure, you could call it a toolbox welded to an opened oxygen tank cabled to a skateboard, but it's a TRASH CANNON to us."
icon_state = "garbagegun"
anchored = FALSE
anchorable_cannon = FALSE
var/fires_before_deconstruction = 5
/obj/structure/cannon/trash/fire()
var/explode_chance = 10
var/used_alt_fuel = reagents.has_reagent(/datum/reagent/fuel, charge_size)
if(used_alt_fuel)
explode_chance += BAD_FUEL_EXPLODE_PROBABILTY
. = ..()
fires_before_deconstruction--
if(used_alt_fuel)
fires_before_deconstruction--
if(prob(explode_chance))
visible_message("<span class='warning'>[src] explodes!</span>")
explosion(src, heavy_impact_range = 1, light_impact_range = 5, flame_range = 5)
return
if(fires_before_deconstruction <= 0)
visible_message("<span class='warning'>[src] falls apart from operation!</span>")
qdel(src)
/obj/structure/cannon/trash/Destroy()
new /obj/item/stack/sheet/metal/five(src.loc)
new /obj/item/stack/rods(src.loc)
. = ..()
#undef BAD_FUEL_DAMAGE_TAX
#undef BAD_FUEL_EXPLODE_PROBABILTY

View File

@@ -0,0 +1,70 @@
/obj/item/stack/cannonball
name = "cannonballs"
desc = "A stack of heavy plasteel cannonballs. Gunnery for the space age!"
icon = 'modular_splurt/icons/obj/stack_objects.dmi'
icon_state = "cannonballs"
max_amount = 14
singular_name = "cannonball"
merge_type = /obj/item/stack/cannonball
throwforce = 10
flags_1 = CONDUCT_1
custom_materials = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT)
resistance_flags = FIRE_PROOF
throw_speed = 5
throw_range = 3
///the type of projectile this type of cannonball item turns into.
var/obj/item/projectile/projectile_type = /obj/item/projectile/bullet/cannonball
/obj/item/stack/cannonball/update_icon_state()
. = ..()
icon_state = (amount == 1) ? "[initial(icon_state)]" : "[initial(icon_state)]_[min(amount, 14)]"
/obj/item/stack/cannonball/fourteen
amount = 14
/obj/item/stack/cannonball/shellball
name = "explosive shellballs"
singular_name = "explosive shellball"
desc = "An explosive anti-material and counter-battery projectile cannonball. Makes great work out of any wall, for easy entrances."
color = "#FF0000"
merge_type = /obj/item/stack/cannonball/shellball
projectile_type = /obj/item/projectile/bullet/cannonball/explosive
/obj/item/stack/cannonball/shellball/seven
amount = 7
/obj/item/stack/cannonball/shellball/fourteen
amount = 14
/obj/item/stack/cannonball/emp
name = "malfunction shots"
singular_name = "malfunction shot"
icon_state = "emp_cannonballs"
desc = "A shot filled with two chambers that combine on impact, creating a chemical EMP. What does any of that mean? Who knows. Modern piracy really lost its soul with these newfangled things."
max_amount = 4
merge_type = /obj/item/stack/cannonball/emp
projectile_type = /obj/item/projectile/bullet/cannonball/emp
/obj/item/stack/cannonball/the_big_one
name = "\"The Biggest Ones\""
singular_name = "\"The Biggest One\""
desc = "An insane amount of explosives jammed into a massive cannonball. The last cannonball you'll ever fire in a fight, mostly because there'll be nothing left to shoot at afterwards."
max_amount = 5
icon_state = "biggest_cannonballs"
merge_type = /obj/item/stack/cannonball/the_big_one
projectile_type = /obj/item/projectile/bullet/cannonball/biggest_one
/obj/item/stack/cannonball/the_big_one/five
amount = 5
/obj/item/stack/cannonball/trashball
name = "trashballs"
singular_name = "trashball"
desc = "A clump of tightly packed garbage. It'll work as a cannonball, but it may be unhealthy to actually put this in a real cannon."
max_amount = 4
icon_state = "trashballs"
merge_type = /obj/item/stack/cannonball/trashball
projectile_type = /obj/item/projectile/bullet/cannonball/trashball
/obj/item/stack/cannonball/trashball/four
amount = 4

View File

@@ -0,0 +1,4 @@
/datum/spellbook_entry/summonsoap
name = "Summon Soap"
spell_type = /obj/effect/proc_holder/spell/targeted/conjure_item/soap
category = "Defensive"

View File

@@ -182,3 +182,15 @@
else
message = "makes a very loud noise."
. = ..()
/datum/emote/living/monkeytwerk
key = "twerk"
key_third_person = "twerk"
message = "shakes it harder than James Russle himself!"
emote_type = EMOTE_AUDIBLE
muzzle_ignore = TRUE
restraint_check = FALSE
/datum/emote/living/monkeytwerk/run_emote(mob/user, params, type_override, intentional)
. = ..()
playsound(user, 'modular_splurt/sound/misc/monkey_twerk.ogg', 50, 1)

View File

@@ -0,0 +1,66 @@
/obj/item/projectile/bullet/cannonball
name = "cannonball"
icon = 'modular_splurt/icons/obj/guns/projectiles.dmi'
icon_state = "cannonball"
damage = 110 //gets set to 100 before first mob impact.
movement_type = FLYING | UNSTOPPABLE
sharpness = NONE
wound_bonus = 0
dismemberment = 0
knockdown = 5 SECONDS
stutter = 10 SECONDS
embedding = null
hitsound = 'sound/effects/meteorimpact.ogg'
hitsound_wall = 'sound/weapons/sonic_jackhammer.ogg'
/obj/item/projectile/bullet/cannonball/prehit(atom/target)
damage -= 10
if(damage < 40)
movement_type &= ~(UNSTOPPABLE)
return ..()
/obj/item/projectile/bullet/cannonball/on_hit(atom/target, blocked = FALSE)
if(blocked == 100)
return ..()
if(isobj(target))
var/obj/hit_object = target
hit_object.take_damage(80, BRUTE)
else if(isclosedturf(target))
damage -= max(damage - 30, 10) //lose extra momentum from busting through a wall
if(!isindestructiblewall(target))
var/turf/closed/hit_turf = target
hit_turf.ScrapeAway()
return ..()
/obj/item/projectile/bullet/cannonball/explosive
name = "explosive shell"
color = "#FF0000"
damage = 40 //set to 30 before first mob impact, but they're gonna be gibbed by the explosion
/obj/item/projectile/bullet/cannonball/explosive/prehit(atom/target)
. = ..()
explosion(target, devastation_range = 2, heavy_impact_range = 3, light_impact_range = 4)
/obj/item/projectile/bullet/cannonball/emp
name = "malfunction shot"
icon_state = "emp_cannonball"
damage = 15 //very low
/obj/item/projectile/bullet/cannonball/emp/prehit(atom/target)
. = ..()
empulse(src, 4, 10)
/obj/item/projectile/bullet/cannonball/biggest_one
name = "\"The Biggest One\""
icon_state = "biggest_one"
damage = 70 //low pierce
/obj/item/projectile/bullet/cannonball/biggest_one/prehit(atom/target)
. = ..()
if(damage < 50)
explosion(target, GLOB.MAX_EX_DEVESTATION_RANGE, GLOB.MAX_EX_HEAVY_RANGE, GLOB.MAX_EX_LIGHT_RANGE, GLOB.MAX_EX_FLASH_RANGE)
/obj/item/projectile/bullet/cannonball/trashball
name = "trashball"
icon_state = "trashball"
damage = 90 //better than the biggest one but no explosion, so kinda just a worse normal cannonball

View File

@@ -0,0 +1,22 @@
/datum/reagent/drug/maint/tar
name = "Maintenance Tar"
description = "An unknown tar that you most likely gotten from an assistant, a bored chemist... or cooked yourself."
reagent_state = LIQUID
color = "#000000"
overdose_threshold = 30
/datum/reagent/drug/maint/tar/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
. = ..()
M.AdjustStun(-10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.AdjustKnockdown(-10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.AdjustUnconscious(-10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.AdjustParalyzed(-10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.AdjustImmobilized(-10 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.adjustOrganLoss(ORGAN_SLOT_LIVER, 1.5 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
/datum/reagent/drug/maint/tar/overdose_process(mob/living/M, delta_time, times_fired)
. = ..()
M.adjustToxLoss(5 * REAGENTS_EFFECT_MULTIPLIER * delta_time)
M.adjustOrganLoss(ORGAN_SLOT_LIVER, 3 * REAGENTS_EFFECT_MULTIPLIER * delta_time)

View File

@@ -0,0 +1,7 @@
/datum/chemical_reaction/maint_tar1
results = list(/datum/reagent/toxin/acid = 1 ,/datum/reagent/drug/maint/tar = 3)
required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/phenol = 1 , /datum/reagent/fuel = 1)
/datum/chemical_reaction/maint_tar2
results = list(/datum/reagent/toxin/acid = 1 ,/datum/reagent/drug/maint/tar = 3)
required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/consumable/enzyme = 3 , /datum/reagent/fuel = 1)

View File

@@ -0,0 +1,8 @@
/obj/effect/proc_holder/spell/targeted/conjure_item/soap
name = "Summon Soap"
desc = "For El Trollage. And maybe a bit of crew's anger too."
charge_max = 100
action_icon = 'icons/obj/items_and_weapons.dmi'
action_icon_state = "soapdeluxe"
item_type = /obj/item/soap/deluxe
delete_old = FALSE

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 B

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Binary file not shown.

View File

@@ -4199,6 +4199,7 @@
#include "modular_splurt\code\game\object\effects\landmarks.dm"
#include "modular_splurt\code\game\object\items\cards_ids.dm"
#include "modular_splurt\code\game\object\items\cosmetics.dm"
#include "modular_splurt\code\game\object\items\granters.dm"
#include "modular_splurt\code\game\object\items\mesmetron.dm"
#include "modular_splurt\code\game\object\items\miscellaneous.dm"
#include "modular_splurt\code\game\object\items\circuitboards\computer_circuitboards.dm"
@@ -4223,6 +4224,8 @@
#include "modular_splurt\code\game\object\structures\tables_racks.dm"
#include "modular_splurt\code\game\object\structures\bed_chairs\beds.dm"
#include "modular_splurt\code\game\object\structures\bed_chairs\chairs.dm"
#include "modular_splurt\code\game\object\structures\cannons\cannon.dm"
#include "modular_splurt\code\game\object\structures\cannons\cannonballs.dm"
#include "modular_splurt\code\game\object\structures\crates_lockers\closets\slaver.dm"
#include "modular_splurt\code\game\object\structures\crates_lockers\closets\secure\security.dm"
#include "modular_splurt\code\game\object\structures\crates_lockers\crates\wooden.dm"
@@ -4295,9 +4298,12 @@
#include "modular_splurt\code\modules\projectiles\guns\ballistic\shotgun.dm"
#include "modular_splurt\code\modules\projectiles\guns\misc\grenade_launcher.dm"
#include "modular_splurt\code\modules\projectiles\projectile\bullets\smg.dm"
#include "modular_splurt\code\modules\projectiles\projectile\bullets\cannonball.dm"
#include "modular_splurt\code\modules\reagents\chemistry\reagents\alcohol_reagents.dm"
#include "modular_splurt\code\modules\reagents\chemistry\reagents\cit_reagents.dm"
#include "modular_splurt\code\modules\reagents\chemistry\reagents\drug_reagents.dm"
#include "modular_splurt\code\modules\reagents\chemistry\reagents\food_reagents.dm"
#include "modular_splurt\code\modules\reagents\chemistry\recipes\drugs.dm"
#include "modular_splurt\code\modules\reagents\chemistry\recipes\lewd.dm"
#include "modular_splurt\code\modules\research\designs\biogenerator_designs.dm"
#include "modular_splurt\code\modules\research\designs\power_designs.dm"
@@ -4310,6 +4316,7 @@
#include "modular_splurt\code\modules\smithing\anvil.dm"
#include "modular_splurt\code\modules\smithing\finished_items.dm"
#include "modular_splurt\code\modules\smithing\smithed_items.dm"
#include "modular_splurt\code\modules\spell\spell_types\conjure.dm"
#include "modular_splurt\code\modules\vending\clothesmate.dm"
#include "modular_splurt\code\modules\vending\security.dm"
#include "tools\Redirector\textprocs.dm"