Honkbots: The Clown's lil helpers. (#31139)

* Honkbots 0.9.0

Old code, needs testing.

* Honkbots 0.9.1

Small Fixes - Part 1

* Honkbot 0.9.1b

Fixes

* Honkbots 0.9.2

Added sound cooldown, fixes.

* Honkbots 0.9.5

Clown Box & Honkbot Assembly Code

* 0.9.5.a

oops

* Honkbots 1.0.0

Final touches and fixes.
Clown Box finished.
Assembly functioning.
Honkbots tested and ready to go.
Its time.

* Honkbots 1.0.1

Initialize and . = ..()

* Honkbots 1.0.2

Fixes and Changes
====
Nerfed Brute/Thermal Resist
Buffed Health (to avoid 1-shot)
Added HONK_BOT define

* Honkbots 1.0.3

Removed the cardboard assembly from death gibs.
Admin Bwoink removed from emagged soundtrack.
Honkbot now release an evil laugh when emagged.
Fixed strange behaviors on emagged level 1
Added a check against stamping multiple cardboard sheets.
Stamping a Clown Box now plays the bike horn, once.
Clown Boxes no longer get automatically placed in hands.
Various other fixes.

* Honkbots 1.0.3a

* Honkbots 1.0.3.b

Fixes.

* Honkbots 1.0.4

*Added an emote ping upon assembly creation.
*Enabled either Theatre or Robotics for access. ((fixing needing both))
*Honkbots are now more forgiving after being hit.
**Airhorn stun_attack now deals slight ear damage, for about 5 seconds.
**Cardboard no longer drops upon death. Robot arms have 50% chance.
**Using a new get_sfx() list when emagged.
**Optimization and other minor fixes.

* Honkbots 1.0.4.a

Missed it.

* Honkbots 1.0.4.b

use(1) and (client)

* Honkbots 1.0.4.c

Moved proc

* Honkbots 1.0.5

*Code Optimization
*Renaming w/ Pen (how could I even forget this)
*Assembly Defines

I'm afraid I'm simply out of my depth with the suggested use(1) rework.

* Honkbots 1.0.5.c

Reworked cardboard stamping.

It now works in the hands and on the ground, either solo or in stacks, and prevent itself being used in backpacks.

* Honkbots 1.0.5.d

Final

* Honkbots 1.0.5.e

comment

* 1.0.5.f

Optimization

* Honkbots 1.0.5.g

Missed requested stuff

* Honkbots 1.0.6

Requested changes.

* Honkbots 1.0.6a

Oops.

* Honkbots 1.0.6.c

Bugfix - Prevent building in backpacks.
Make sure they spawn on turf.

* Honkbots 1.0.7

one less spawn(0)
flag optimization
else return ..()

* Honkbots 1.0.7.a

Get rids of a lot of client checks at the cost of automatic AI retoration.

* Honkbots 1.0.7.b

Added judgment_criteria()
changed assess_threat to use judgment

* Honkbots 1.0.7.c

final = NONE
This commit is contained in:
Mercenaryblue
2017-10-15 17:43:58 -04:00
committed by CitadelStationBot
parent be2dc49384
commit 3690fc56c2
11 changed files with 461 additions and 2 deletions

View File

@@ -181,4 +181,4 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmaglass,
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))

View File

@@ -34,6 +34,7 @@
#define FLOOR_BOT 4 // Floorbots
#define CLEAN_BOT 8 // Cleanbots
#define MED_BOT 16 // Medibots
#define HONK_BOT 32 // Honkbots & ED-Honks
//AI notification defines
#define NEW_BORG 1
@@ -41,3 +42,7 @@
#define RENAME 3
#define AI_SHELL 4
#define DISCONNECT 5
//Assembly defines
#define ASSEMBLY_FIRST_STEP 0
#define ASSEMBLY_SECOND_STEP 1

View File

@@ -256,6 +256,18 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \
/obj/item/stack/sheet/cardboard/fifty
amount = 50
/obj/item/stack/sheet/cardboard/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/stamp/clown) && !istype(loc, /obj/item/storage))
var/atom/droploc = drop_location()
if(use(1))
playsound(I, 'sound/items/bikehorn.ogg', 50, 1, -1)
to_chat(user, "<span class='notice'>You stamp the cardboard! Its a clown box! Honk!</span>")
if (amount >= 0)
new/obj/item/storage/box/clown(droploc) //bugfix
else
. = ..()
/*
* Runed Metal
*/

View File

@@ -607,6 +607,29 @@
playsound(loc, "rustle", 50, 1, -5)
user.visible_message("<span class='notice'>[user] hugs \the [src].</span>","<span class='notice'>You hug \the [src].</span>")
/////clown box & honkbot assembly
obj/item/storage/box/clown
name = "clown box"
desc = "A colorful cardboard box for the clown"
icon_state = "clownbox"
illustration = null
/obj/item/storage/box/clown/attackby(obj/item/I, mob/user, params)
if((istype(I, /obj/item/bodypart/l_arm/robot)) || (istype(I, /obj/item/bodypart/r_arm/robot)))
if(contents.len) //prevent accidently deleting contents
to_chat(user, "<span class='warning'>You need to empty [src] out first!</span>")
return
if(!user.temporarilyRemoveItemFromInventory(I))
return
qdel(I)
to_chat(user, "<span class='notice'>You add some wheels to the [src]! You've got an honkbot assembly now! Honk!</span>")
var/obj/item/honkbot_assembly/A = new
qdel(src)
user.put_in_hands(A)
else
return ..()
//////
/obj/item/storage/box/hug/medical/PopulateContents()
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/ointment(src)
@@ -730,7 +753,7 @@
/obj/item/storage/box/ingredients //This box is for the randomely chosen version the chef spawns with, it shouldn't actually exist.
name = "ingredients box"
illustration = "fruit"
var/theme_name
var/theme_name
/obj/item/storage/box/ingredients/Initialize()
. = ..()

View File

@@ -180,4 +180,6 @@
soundin = pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg')
if("law")
soundin = pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg')
if("honkbot_e")
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bcreep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
return soundin

View File

@@ -347,6 +347,51 @@
S.name = created_name
qdel(src)
//Honkbot Assembly
/obj/item/honkbot_assembly
name = "incomplete honkbot assembly"
desc = "The clown's up to no good once more"
icon = 'icons/mob/aibots.dmi'
icon_state = "honkbot_arm"
var/build_step = ASSEMBLY_FIRST_STEP
var/created_name = "Honkbot"
/obj/item/honkbot_assembly/attackby(obj/item/I, mob/user, params)
if(isprox(I) && (build_step == ASSEMBLY_FIRST_STEP))
if(!user.temporarilyRemoveItemFromInventory(I))
return
build_step++
to_chat(user, "<span class='notice'>You add the [I] to [src]!</span>")
icon_state = "honkbot_proxy"
name = "incomplete Honkbot assembly"
qdel(I)
else if(istype(I, /obj/item/bikehorn) && (build_step == ASSEMBLY_SECOND_STEP))
if(istype(loc, /obj/item/storage/backpack)) //don't build them in your backpacks!
return
if(!user.temporarilyRemoveItemFromInventory(I))
return
to_chat(user, "<span class='notice'>You add the [I] to [src]! Honk!</span>")
var/T = get_turf(loc) //important to spawn on turf.
var/mob/living/simple_animal/bot/honkbot/S = new(drop_location(T))
S.name = created_name
S.spam_flag = TRUE // only long enough to hear the first ping.
addtimer(CALLBACK (S, .mob/living/simple_animal/bot/honkbot/proc/react_ping), 5)
qdel(I)
qdel(src)
else if(istype(I, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
else return ..()
//Secbot Assembly
/obj/item/secbot_assembly
name = "incomplete securitron assembly"

View File

@@ -0,0 +1,371 @@
/mob/living/simple_animal/bot/honkbot
name = "\improper honkbot"
desc = "A little robot. It looks happy with its bike horn."
icon = 'icons/mob/aibots.dmi'
icon_state = "honkbot"
density = FALSE
anchored = FALSE
health = 25
maxHealth = 25
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
pass_flags = PASSMOB
radio_key = /obj/item/device/encryptionkey/headset_service //doesn't have security key
radio_channel = "Service" //Doesn't even use the radio anyway.
bot_type = HONK_BOT
model = "Honkbot"
bot_core_type = /obj/machinery/bot_core/honkbot
window_id = "autohonk"
window_name = "Honkomatic Bike Horn Unit v1.0.7"
data_hud_type = DATA_HUD_SECURITY_BASIC // show jobs
var/honksound = 'sound/items/bikehorn.ogg' //customizable sound
var/spam_flag = FALSE
var/cooldowntime = 30
var/cooldowntimehorn = 10
var/mob/living/carbon/target
var/oldtarget_name
var/target_lastloc = FALSE //Loc of target when arrested.
var/last_found = FALSE //There's a delay
var/threatlevel = FALSE
var/declare_arrests = FALSE // speak, you shall not, unless to Honk
var/idcheck = TRUE
var/fcheck = TRUE
var/check_records = TRUE
var/arrest_type = FALSE
var/weaponscheck = TRUE
/mob/living/simple_animal/bot/honkbot/Initialize()
. = ..()
icon_state = "honkbot[on]"
auto_patrol = TRUE
var/datum/job/clown/J = new/datum/job/clown
access_card.access += J.get_access()
prev_access = access_card.access
/mob/living/simple_animal/bot/honkbot/proc/spam_flag_false() //used for addtimer
spam_flag = FALSE
/mob/living/simple_animal/bot/honkbot/proc/blink_end() //used for addtimer
icon_state = "honkbot[on]"
/mob/living/simple_animal/bot/honkbot/proc/sensor_blink()
icon_state = "honkbot-c"
addtimer(CALLBACK(src, .proc/blink_end), 5)
//honkbots react with sounds.
/mob/living/simple_animal/bot/honkbot/proc/react_ping()
playsound(src, 'sound/machines/ping.ogg', 50, 1, -1) //the first sound upon creation!
spam_flag = TRUE
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), 18) // calibrates before starting the honk
/mob/living/simple_animal/bot/honkbot/proc/react_buzz()
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1, -1)
sensor_blink()
/mob/living/simple_animal/bot/honkbot/bot_reset()
..()
target = null
oldtarget_name = null
anchored = FALSE
walk_to(src,0)
last_found = world.time
spam_flag = FALSE
/mob/living/simple_animal/bot/honkbot/set_custom_texts()
text_hack = "You overload [name]'s sound control system"
text_dehack = "You reboot [name] and restore the sound control system."
text_dehack_fail = "[name] refuses to accept your authority!"
/mob/living/simple_animal/bot/honkbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Honkomatic Bike Horn Unit v1.0.7 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=[TRUE]'>[on ? "On" : "Off"]</A>" )
if(!locked || issilicon(user) || IsAdminGhost(user))
dat += text({"<BR> Auto Patrol: []"},
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/honkbot/proc/judgement_criteria()
var/final = NONE
if(check_records)
final = final|JUDGE_RECORDCHECK
if(emagged)
final = final|JUDGE_EMAGGED
return final
/mob/living/simple_animal/bot/honkbot/proc/retaliate(mob/living/carbon/human/H)
var/judgement_criteria = judgement_criteria()
threatlevel = H.assess_threat(judgement_criteria)
threatlevel += 6
if(threatlevel >= 4)
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == "harm")
retaliate(H)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
return ..()
/mob/living/simple_animal/bot/honkbot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM).
return
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Check for welding tool to fix #2432.
retaliate(user)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
..()
/mob/living/simple_animal/bot/honkbot/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='danger'>You short out [src]'s sound control system. It gives out an evil laugh!!</span>"
oldtarget_name = user.name
audible_message("<span class='danger'>[src] gives out an evil laugh!</span>")
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
icon_state = "honkbot[on]"
/mob/living/simple_animal/bot/honkbot/bullet_act(obj/item/projectile/Proj)
if((istype(Proj,/obj/item/projectile/beam)) || (istype(Proj,/obj/item/projectile/bullet) && (Proj.damage_type == BURN))||(Proj.damage_type == BRUTE) && (!Proj.nodamage && Proj.damage < health))
retaliate(Proj.firer)
..()
/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A)
if(!on)
return
if(iscarbon(A))
var/mob/living/carbon/C = A
if (emagged <= 1)
honk_attack(A)
else
if(!C.IsStun() || arrest_type)
stun_attack(A)
..()
else if (!spam_flag) //honking at the ground
bike_horn(A)
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
playsound(src, honksound, 50, 1, -1)
var/obj/item/I = AM
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
var/mob/living/carbon/human/H = I.thrownby
retaliate(H)
..()
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
if (emagged <= 1)
if (!spam_flag)
playsound(src, honksound, 50, 1, -1)
spam_flag = TRUE //prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
else if (emagged == 2) //emagged honkbots will spam short and memorable sounds.
if (!spam_flag)
playsound(src, "honkbot_e", 50, 0)
spam_flag = TRUE // prevent spam
icon_state = "honkbot-e"
addtimer(CALLBACK(src, .proc/blink_end), 30)
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/honk_attack(mob/living/carbon/C) // horn attack
if(!spam_flag)
playsound(loc, honksound, 50, 1, -1)
spam_flag = TRUE // prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/stun_attack(mob/living/carbon/C) // airhorn stun
if(!spam_flag)
playsound(loc, 'sound/items/AirHorn.ogg', 100, 1, -1) //HEEEEEEEEEEEENK!!
sensor_blink()
if(spam_flag == 0)
if(ishuman(C))
C.stuttering = 20
C.adjustEarDamage(0, 5) //far less damage than the H.O.N.K.
C.Jitter(50)
C.Knockdown(60)
var/mob/living/carbon/human/H = C
if(client) //prevent spam from players..
spam_flag = TRUE
if (emagged <= 1) //HONK once, then leave
var/judgement_criteria = judgement_criteria()
threatlevel = H.assess_threat(judgement_criteria)
threatlevel -= 6
target = oldtarget_name
else // you really don't want to hit an emagged honkbot
threatlevel = 6 // will never let you go
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
add_logs(src,C,"honked")
C.visible_message("<span class='danger'>[src] has honked [C]!</span>",\
"<span class='userdanger'>[src] has honked you!</span>")
else
C.stuttering = 20
C.Knockdown(80)
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
/mob/living/simple_animal/bot/honkbot/handle_automated_action()
if(!..())
return
switch(mode)
if(BOT_IDLE) // idle
walk_to(src,0)
look_for_perp()
if(!mode && auto_patrol)
mode = BOT_START_PATROL
if(BOT_HUNT)
// if can't reach perp for long enough, go idle
if(frustration >= 5) //gives up easier than beepsky
walk_to(src,0)
back_to_idle()
return
if(target) // make sure target exists
if(Adjacent(target) && isturf(target.loc))
if(threatlevel <= 4)
honk_attack(target)
else
if(threatlevel >= 6)
set waitfor = 0
stun_attack(target)
anchored = FALSE
target_lastloc = target.loc
return
else // not next to perp
var/turf/olddist = get_dist(src, target)
walk_to(src, target,1,4)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(BOT_START_PATROL)
look_for_perp()
start_patrol()
if(BOT_PATROL)
look_for_perp()
bot_patrol()
return
/mob/living/simple_animal/bot/honkbot/proc/back_to_idle()
anchored = FALSE
mode = BOT_IDLE
target = null
last_found = world.time
frustration = 0
INVOKE_ASYNC(src, .proc/handle_automated_action) //responds quickly
/mob/living/simple_animal/bot/honkbot/proc/back_to_hunt()
anchored = FALSE
frustration = 0
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action) // responds quickly
/mob/living/simple_animal/bot/honkbot/proc/look_for_perp()
anchored = FALSE
for (var/mob/living/carbon/C in view(7,src))
if((C.stat) || (C.handcuffed))
continue
if((C.name == oldtarget_name) && (world.time < last_found + 100))
continue
var/judgement_criteria = judgement_criteria()
threatlevel = C.assess_threat(judgement_criteria)
if(threatlevel <= 3)
if(C in view(4,src)) //keep the range short for patrolling
if(!spam_flag)
bike_horn()
else if(threatlevel >= 10)
bike_horn() //just spam the shit outta this
else if(threatlevel >= 4)
if(!spam_flag)
target = C
oldtarget_name = C.name
bike_horn()
speak("Honk!")
visible_message("<b>[src]</b> starts chasing [C.name]!")
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
/mob/living/simple_animal/bot/honkbot/explode()
walk_to(src,0)
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
//doesn't drop cardboard nor its assembly, since its a very frail material.
if(prob(50))
new /obj/item/bodypart/l_arm/robot/(Tsec)
new /obj/item/bikehorn(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/oil(loc)
..()
/mob/living/simple_animal/bot/honkbot/attack_alien(var/mob/living/carbon/alien/user as mob)
..()
if(!isalien(target))
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM)
if(ismob(AM))
if(prob(30)) //you're far more likely to trip on a honkbot
var/mob/living/carbon/C = AM
if(!istype(C) || !C || in_range(src, target))
return
C.visible_message("<span class='warning'>[pick( \
"[C] dives out of [src]'s way!", \
"[C] stumbles over [src]!", \
"[C] jumps out of [src]'s path!", \
"[C] trips over [src] and falls!", \
"[C] topples over [src]!", \
"[C] leaps out of [src]'s way!")]</span>")
C.Knockdown(10)
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1, -1)
speak("Honk!")
sensor_blink()
return
..()
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

View File

@@ -1787,6 +1787,7 @@
#include "code\modules\mob\living\simple_animal\bot\construction.dm"
#include "code\modules\mob\living\simple_animal\bot\ed209bot.dm"
#include "code\modules\mob\living\simple_animal\bot\floorbot.dm"
#include "code\modules\mob\living\simple_animal\bot\honkbot.dm"
#include "code\modules\mob\living\simple_animal\bot\medbot.dm"
#include "code\modules\mob\living\simple_animal\bot\mulebot.dm"
#include "code\modules\mob\living\simple_animal\bot\secbot.dm"