generic gas #256

Parent #141Owner #361Flags read, fertileSource hellcore/hellcore.db

Aliases: generic gas, gas

19 verbs · 49 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
creature_heartbeatthis none thisrxd#25618
heartbeatthis none thisrxd#25614
add_tothis none thisrxd#25635
movetothis none thisrxd#25619
recyclethis none thisrxd#2562
on_spawnthis none thisrxd#2561
_flowthis none thisrxd#25670
_increasethis none thisrxd#25642
_flow_throughthis none thisrxd#25630
_decreasethis none thisrxd#25633
look_place_msgthis none thisrxd#25613
amountthis none thisrxd#25610
hear_event_movethis none thisrxd#2560
hear_event_arrivethis none thisrxd#2560
inhaled_bythis none thisrxd#25617
tree_tagthis none thisrxd#25632
remove_fromthis none thisrxd#25630
set_amountthis none thisrxd#25628
entombthis none thisrxd#2563

Properties

PropertyDefinerFlagsOwnerValue
drugs#256rc#361{}
opaque#256rc#3611
spread_rate#256rc#3611
heart#256rc#3610
last_heartbeat#256rc#3610
descriptive_names#256rc#361{"gas"}
closed_door_msg#256rc#361{"%Gas seeps in through %dt.", "%Gas filters in from %dt.", "%Gas rolls in from %dt."}
open_door_msg#256rc#361{}
through_msg#256rc#361{"%Gas drifts in from %dt.", "%Gas rolls in from %dt.", "%Gas billows in from %dt."}
threshold#256rc#36120
increase_msg#256rc#361{"You notice a growing haze of %gas.", "%Gas hangs thickly in the air.", "%Gas fills the air, obscuring your sight."}
dissipate_msg#256rc#361"The last of the %gas dissipates."
decrease_msg#256rc#361{"The %gas thins out into a haze.", "You notice some breaks in the %gas.", "The %gas swirls around you."}
dissipation_inside#256rc#3611
dissipation_outside#256rc#36112
help_msg#256rc#361
list of 72{"HELP! GAS! I mean hello, welcome to $gas help.", "", "INTRODUCTION: $gas is a complicated, psuedorealistic implementation of gas-like things. It can be fun for small things (farts, grenades, killing people). IT WILL BREAK EVERYTHING if you use it on a large scale. Use $decals for that.", "", "How $gas works:", " - Like $decals, $gases are instanced children which exist in a room. The ", " same prop, .accumulation, that holds the amount of $decal in a room, also ", " works for $gas.", "", " - $gases.yourgas:add_to(room, amount) adds a gas to a room. Gases can ", " only be in rooms, and never on (in?) people, unlike $decals.", "", " - $gas has a :heartbeat, which calls :_flow. Gases flow into other rooms ", " via exits, depending on how much is in a room. Except for special cases:", " level = (.accumulation / . threshold) (default 20)", " flow = level * .spread_rate (default 1)", "", " - The 'level' above, i.e., the level of gas thickness in a room, can be ", " affected (for flow calculation) by a closed door:", " effective_level = level - closed_door.filtration", "", " - After :_flow, $gas also dissipates a bit each heartbeat, inside the ", " amount is .dissipation_inside, outside is .dissipation_outside. Someday I ", " should use room.size...", "", "- .drugs should be in the form {drugspec, drugspec, ...}. Each drugspec can be", " a plain drug object, or a list, {drug, dose_chance [, dose_ratio]}. There is ", " a dose_chance/100 chance (default 100), each heartbeat, of inhaling ", " gasunits/dose_ratio (default 1) units of drug. Gasunits is given by the formula:", "", " gil_float_to_int(tofloat(.accumulation) / tofloat(.threshold))", "", " Which means that the inhalation is approximately equivalent to the 'gas level' above.", "", " - When a gas is inhaled, :inhaled_by(who, amount of gas) is called, which", " you can use if players are to inhale a gas directly (without it being ", " instantiated as a room object.) Gases are ingested with the inhalation", " $drug_vector, which you may also want to look at.", "", " Messages:", " Nearly all messages are level-dependent (see above). ", " For level-varying messages, the gas level is the index of the shown ", " messages (gas level 2 = msg[min(2,$)].)", "", " Also, \"%gas\" will be replaced, in all messages, by a random element ", " of .descriptive_names. \"%Gas\", with a capital G, capitalizes the ", " randomly-selected name.", "", " Level-varying messages:", " .decrease_msg -- shown when gas decreases to new level", " .increase_msg -- shown when gas increases to new level", " .through_msg -- shown in exit.otherside.location when gas comes ", " in through non-door exits.", " .open_door_msg -- as above, for open doors (if blank, uses through_msg)", " .closed_door_msg -- as above, closed doors, but also uses effective_level.", " .look_place_msg -- the usual, selected by level (if blank, uses increase_msg)", "", " Level-invariant messages; if lists, selects a random element:", " .onset_msg -- shown when the gas first accumulates (optional)", " .dissipate_msg -- shown when the gas amount hits 0", "", " Other properties:", " .description -- you know, for looking at", " .opaque -- if this is 0, no messages are ever shown.", " .max_accumulation -- if this gets hit, :_flow is immediately called with a ", " pressure argument, which ensures at least that much will flow out of the ", " room, if at all possible.", " .exclusive_to -- SET THIS, it does what it does for $decals", " .descriptive_names -- SET THIS, see above. Don't let it just be {\"gas\"}.", "", "IF THIS IS TOO MUCH, and I understand if it is, just take a look at #266737 (weed smoke), which was the first gas for hellmoo and has been tested extensively - and uses pretty much every feature.", "----"}
dose_ratio#256rc#3611
onset_msg#256rc#361""
debugger#256rc#361#-1
smell_msg#256rc#361""
floats#256rc#3611
exclusive_to#141rc#361#57516
look_place_msg#141rc#361{"There is a light haze in the air.", "%Gas hangs thickly in the air.", "%Gas fills the air, obscuring your sight."}
stick_time#141r#361<clear>
lifespan#141rc#361<clear>
accumulation#141r#3610
junk_ok#141rc#361<clear>
look_person_msg#141rc#361<clear>
wipeable#141rc#361<clear>
clean_msg#141rc#361<clear>
clean_last_msg#141rc#361<clear>
disperse_msg#141rc#361<clear>
blood#141rc#361<clear>
infect_chance#141rc#3615
max_accumulation#141rc#361100
nutrition#141rc#361<clear>
lick_self_msg#141rc#361<clear>
look_place_air_msg#141rc#361<clear>
falls#141rc#3610
aliases#1rc#361{"generic gas", "gas"}
description#1rc#361"Nothing special, but it looks like you could choke on it."
object_size#1r#29{20902, 1298434096}
hidden_verbs#1rc#361<clear>
phelp_msg#1rc#361<clear>
weight#1rc#361<clear>
owner_verbs#1rc#361<clear>
plural_name#1rc#361<clear>
client_image#1rc#361<clear>
listening#1rc#361<clear>

Ancestry

Ancestors (nearest first): #141 generic decal#1 root

Children: none

Call graph

calls n256_0 #256:creature_heartbeat n18_43 #18:gil_float_to_int n256_0->n18_43 n256_14 #256:inhaled_by n256_0->n256_14 n256_9 #256:_decrease n256_0->n256_9 n103_2 #103:junk n256_9->n103_2 n20_15 #20:capitalize n256_9->n20_15 n256_1 #256:heartbeat n256_1->n18_43 n256_1->n256_9 n256_6 #256:_flow n256_1->n256_6 n256_6->n256_9 n20_59 #20:name_and_number n256_6->n20_59 n57_1 #57:_recycle n256_6->n57_1 n256_11 #256:amount n256_6->n256_11 n256_8 #256:_flow_through n256_6->n256_8 n48_8 #48:suspend_if_needed n256_6->n48_8 n256_2 #256:add_to n103_1 #103:spawn n256_2->n103_1 n256_2->n20_59 n256_3 #256:moveto n256_3->n20_59 n256_3->n103_2 n256_4 #256:recycle n150_2 #150:unregister n256_4->n150_2 n1_1 #1:recycle n256_4->n1_1 n256_5 #256:on_spawn n150_0 #150:register n256_5->n150_0 n256_8->n256_2 n256_8->n256_11 n256_8->n20_15 n20_34 #20:pronoun_sub n256_8->n20_34 n256_7 #256:_increase n256_7->n256_6 n256_7->n20_15 n256_10 #256:look_place_msg n256_10->n20_15 n256_15 #256:tree_tag n256_15->n20_59 n20_1 #20:left n256_15->n20_1 n20_5 #20:from_list n256_15->n20_5 n20_101 #20:smart_abbrev n256_15->n20_101 n256_17 #256:set_amount n256_17->n256_2 n256_16 #256:remove_from n256_17->n256_16 n256_18 #256:entomb n256_18->n150_2 n1_68 #1:entomb n256_18->n1_68

Source

creature_heartbeat

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1if (this.f || (!this.drugs))
2return;
3endif
4who = args[1];
5if ((who == this) || (!is_a(who, $creature)))
6"this actually happens";
7return;
8endif
9if (is_a(who, #31501))
10"robot, doesn't breathe!";
11return;
12endif
13floatlevel = tofloat(this.accumulation) / tofloat(this.threshold);
14units = $math_utils:gil_float_to_int(floatlevel);
15if (units)
16this:inhaled_by(who, units);
17this:_decrease(units);
18endif

heartbeat

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1if (this.f)
2raise(E_PERM, "this shouldn't be heartbeating");
3endif
4amt_left = this:_flow();
5if (!amt_left)
6return;
7endif
8dsp = this.location.outdoor ? this.dissipation_outside | this.dissipation_inside;
9if (typeof(dsp) == FLOAT)
10dsp = $math_utils:gil_float_to_int(dsp);
11endif
12if (dsp)
13this:_decrease(dsp);
14endif

add_to

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1"$gas:add_to(OBJ dest [, INT amount [, OBJ source]]) => OBJ gas.";
2"Adds the amount to this type of gas if it already exists at dest. If this gas doesn't exist at dest, create a new gas object and move it.";
3{dest, ?amount = 1, ?source = #-1} = args;
4if (!valid(dest))
5return;
6endif
7excluder = this.exclusive_to;
8if (valid(excluder) && (o = dest:occupants(excluder)))
9o = o[1];
10if (is_a(excluder, o))
11o:_increase(amount, source);
12return o;
13endif
14endif
15class = this.f ? this | parent(this);
16if (dest:acceptable(class))
17if (gamevalid(o = $rpg:spawn(class)))
18if (!is_a(o, class))
19#7195:tell("Got non-class ", $su:nn(o), " from spawn!");
20return #-1;
21endif
22real_o = o:moveto(dest, amount, source);
23if (!is_a(real_o, class))
24#7195:tell("Got non-class ", $su:nn(real_o), " from o:moveto!");
25return #-1;
26endif
27if (o == real_o)
28o:_increase(amount, source);
29endif
30return real_o;
31else
32raise(E_INVARG, "Unable to spawn " + tostr(class));
33return #-1;
34endif
35endif

moveto

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1{where, ?new_accum = this.accumulation, ?source = #-1} = args;
2if (!gamevalid(where))
3raise(E_INVARG);
4endif
5if ((!this.f) && (other = where:occupants(this.exclusive_to)))
6for x in (other)
7if (!gamevalid(x))
8#7195:tell("Got invalid ", $su:nn(x), " from occupants in gas:moveto");
9move(this, where);
10endif
11endfor
12other = other[1];
13other:_increase(new_accum, source);
14$rpg:junk(this);
15return other;
16else
17move(this, where);
18return this;
19endif

recycle

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1$heart:unregister(this);
2return pass(@args);

on_spawn

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1$heart:register(this);

_flow

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1":_flow([INT pressure [, OBJ exit_from]]) - pump this out of its location";
2{?pressure = 0, ?exit_from = #-1} = args;
3if (!is_a(this.location, $room))
4#7195:tell("[g] gas in non-room: ", $su:nn(this.location));
5return $recycler:_recycle(this);
6endif
7"return this.accumulation";
8if (pressure < 0)
9raise(E_INVARG, "pressure", pressure);
10return 0;
11endif
12if (!pressure)
13pressure = max(0, this.accumulation - this.max_accumulation);
14endif
15"first, find levels";
16exits = this.location:exits();
17exits = {@exits, @this.location:occupants(#82484)};
18flows = {};
19rate = this.spread_rate;
20amt = this.accumulation;
21to_flow = 0;
22for e in (exits)
23if (e == exit_from)
24flows = {@flows, 0};
25continue;
26endif
27level = amt / this.threshold;
28dest = valid(e.otherside) ? e.otherside.location | #-1;
29if (!valid(dest))
30level = 0;
31elseif (is_a(e, $door) || is_a(e, $window))
32if (!e.open)
33level = max(0, level - e.filtration);
34endif
35elseif (filt = `e.filtration ! E_PROPNF => 0')
36level = max(0, level - filt);
37endif
38if (valid(dest) && (destamt = this:amount(dest)))
39destlevel = destamt / this.threshold;
40if (valid(this.debugger))
41this.debugger:tell("[g] from: ", $su:nn(this.location), " (", level, ") to ", $su:nn(dest), " (", destlevel, ")");
42endif
43level = max(0, level - destlevel);
44endif
45f = max(level, rate * (level - 1));
46flows = {@flows, f};
47to_flow = to_flow + f;
48endfor
49if (!to_flow)
50return amt;
51endif
52levels_total = to_flow;
53to_flow = min(amt, to_flow + (pressure / 2));
54rate = tofloat(rate);
55flowed = 0;
56for i in [1..length(flows)]
57if (!flows[i])
58continue;
59endif
60adjusted = (tofloat(to_flow) / tofloat(levels_total)) * tofloat(flows[i]);
61exit = exits[i];
62if (adjusted >= 1.0)
63level = max(1, toint(adjusted / rate));
64adjusted = toint(adjusted);
65this:_flow_through(adjusted, level, exit);
66flowed = flowed + adjusted;
67endif
68$cu:sin();
69endfor
70return this:_decrease(flowed);

_increase

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1":_increase(INT amt [, OBJ source]) => internal verb to increase gas instance accumulation.";
2{amt, ?source = #-1} = args;
3if (amt < 1)
4return this.accumulation;
5endif
6old_was_zero = this.accumulation == 0;
7oldlevel = this.accumulation / this.threshold;
8this.accumulation = this.accumulation + amt;
9if (valid(this.debugger))
10this.debugger:tell("[g] ", this.location.name, " +", amt, " = ", this.accumulation, old_was_zero ? " (NEW)" | "");
11endif
12newlevel = this.accumulation / this.threshold;
13if (this.opaque && (source != #-1))
14if ((newlevel > oldlevel) && (length(this.increase_msg) > oldlevel))
15msg = this.increase_msg[min(newlevel, $)];
16name = this.descriptive_names[random($)];
17namec = $su:capitalize(name);
18msg = $su:subst(msg, {{"%Gas", namec}, {"%gas", name}}, 1);
19this.location:announce_all(msg);
20elseif (old_was_zero)
21msg = this.onset_msg;
22if (msg)
23if (typeof(msg) == LIST)
24msg = msg[random($)];
25endif
26name = this.descriptive_names[random($)];
27namec = $su:capitalize(name);
28msg = $su:subst(msg, {{"%Gas", namec}, {"%gas", name}}, 1);
29this.location:announce_all(msg);
30endif
31endif
32endif
33over = this.accumulation - this.max_accumulation;
34if (over > 0)
35"force movement";
36this:_flow(over, source);
37endif
38if (is_a(this, $gas))
39return this.accumulation;
40else
41return 0;
42endif

_flow_through

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1{amount, level, exit} = args;
2target = exit.otherside.location;
3if (valid(this.debugger))
4this.debugger:tell(tostr("[g] ", this.location.name, " -> ", target.name, " (", level, ")"));
5endif
6target_level = this:amount(target) / this.threshold;
7if ((target_level < level) && this.opaque)
8if (is_a(exit, $door))
9if (exit.open)
10if (this.open_door_msg)
11msgs = this.open_door_msg;
12else
13msgs = this.through_msg;
14endif
15else
16msgs = this.closed_door_msg;
17endif
18else
19msgs = this.through_msg;
20endif
21if (target_level < length(msgs))
22msg = msgs[min(level, $)];
23name = this.descriptive_names[random($)];
24namec = $su:capitalize(name);
25msg = $su:subst(msg, {{"%Gas", namec}, {"%gas", name}}, 1);
26msg = $su:ps(msg, #-1, exit.otherside, target);
27target:announce_all(msg);
28endif
29endif
30this:add_to(target, amount, exit.otherside);

_decrease

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1":_decrease(INT amt) => internal verb to decrease gas instance accumulation.";
2{amt} = args;
3if (amt < 1)
4return this.accumulation;
5endif
6oldlevel = this.accumulation / this.threshold;
7this.accumulation = max(0, this.accumulation - amt);
8if (valid(this.debugger))
9this.debugger:tell(tostr("[g] ", this.location.name, " -", amt, " = ", this.accumulation));
10endif
11newlevel = this.accumulation / this.threshold;
12msg = "";
13if (this.opaque)
14if (((newlevel < oldlevel) && (newlevel > 0)) && (newlevel <= length(this.decrease_msg)))
15msg = this.decrease_msg[min(newlevel, $)];
16elseif (!this.accumulation)
17msg = this.dissipate_msg;
18if (typeof(msg) == LIST)
19msg = msg[random($)];
20endif
21endif
22endif
23if (msg)
24name = this.descriptive_names[random($)];
25namec = $su:capitalize(name);
26msg = $su:subst(msg, {{"%Gas", namec}, {"%gas", name}}, 1);
27this.location:announce_all(msg);
28endif
29if (!this.accumulation)
30$rpg:junk(this);
31return 0;
32endif
33return this.accumulation;

look_place_msg

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1if (!this.opaque)
2return "";
3endif
4level = this.accumulation / this.threshold;
5if (this.look_place_msg)
6msg = this.look_place_msg[max(1, min(level, $))];
7else
8msg = this.increase_msg[max(1, min(level, $))];
9endif
10name = this.descriptive_names[random($)];
11namec = $su:capitalize(name);
12msg = $su:subst(msg, {{"%Gas", namec}, {"%gas", name}}, 1);
13return msg;

amount

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1":amount(OBJ location) => amount of this gas at location";
2{loc} = args;
3class = this.f ? this | parent(this);
4o = loc:occupants(class);
5if (o)
6o = o[1];
7return o.accumulation;
8else
9return 0;
10endif

hear_event_move

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

No program (verb defined but unprogrammed).

hear_event_arrive

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

No program (verb defined but unprogrammed).

inhaled_by

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1":inhaled_by(OBJ creature, INT units) => cause effects of inhaling the gas to creature. units is in accumulation units of gas.";
2{who, units} = args;
3for drug in (this.drugs)
4dose_ratio = this.dose_ratio;
5if (typeof(drug) == LIST)
6{drug, dose_chance, ?dose_ratio = this.dose_ratio} = drug;
7if (random(100) > dose_chance)
8continue;
9endif
10endif
11doses = units / dose_ratio;
12"1 dose, orally, quiet";
13if (valid(this.debugger))
14this.debugger:tell("[g] ", who.name, " ingested ", doses, " of ", drug.name, " at ", who.location.name);
15endif
16who:ingest(drug, doses, $drug_vectors.inhalation, 1);
17endfor

tree_tag

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1thr = this.threshold;
2di = this.dissipation_inside;
3do = this.dissipation_outside;
4max = this.max_accumulation;
5opq = this.opaque;
6drugs = this.drugs;
7sr = this.spread_rate;
8r = tostr($ansi.cyan, $ansi.bold_on, "s", sr, " t", thr, " m", max, " d", di, "&", do);
9if (!opq)
10r = r + " (!opq)";
11endif
12if (drugs)
13cleandrugs = {};
14for d in (drugs)
15if (typeof(d) == LIST)
16cleandrugs = {@cleandrugs, d[1]};
17else
18cleandrugs = {@cleandrugs, d};
19endif
20endfor
21drugs = cleandrugs;
22r = (r + " ") + $ansi.bold_off;
23if (length(drugs) == 1)
24r = r + $su:left(drugs[1].name, -3);
25else
26r = r + $su:from_list($su:smart_abbrev($lu:map_prop(drugs, "name"), 3), "/");
27endif
28endif
29if ((valid(this.exclusive_to) && (this.exclusive_to != this)) && ((!this.f) && (this.exclusive_to != parent(this))))
30r = (r + "  excl: ") + $su:nn(this.exclusive_to);
31endif
32return r + $ansi.reset;

remove_from

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

Source

1"$gas:remove_from(OBJ where [, INT amount]) => OBJ gas.";
2"Removes the amount (default 1) from this gas at where, if it exists there. #-1 is returned if no gas was there, or if the gas has now been decreased to 0.";
3{where, ?amount = 1} = args;
4if (!valid(where))
5return #-1;
6endif
7excluder = this.exclusive_to;
8gas_obj = #-1;
9if (valid(excluder) && (o = where:occupants(excluder)))
10o = o[1];
11if (is_a(o, excluder))
12gas_obj = o;
13endif
14endif
15if (!valid(gas_obj))
16class = this.f ? this | parent(this);
17if (o = where:occupants(class))
18gas_obj = o[1];
19endif
20endif
21if (!valid(gas_obj))
22return #-1;
23else
24amt_left = gas_obj:_decrease(amount);
25if (!amt_left)
26return #-1;
27else
28return gas_obj;
29endif
30endif

set_amount

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1"$gas:set_amount(OBJ where, INT amount) => OBJ gas.";
2"Ensures that the amount of this gas at 'where' is 'amount'. Increases or decreases the gas there as necessary. The obj returned is the resulting gas object, or #-1 if amount is 0 (or less).";
3{where, amount} = args;
4if (amount <= 0)
5this:remove_from(where, this.max_accumulation);
6endif
7gas_obj = #-1;
8excluder = this.exclusive_to;
9if (valid(excluder) && (o = where:occupants(excluder)))
10gas_obj = o[1];
11else
12class = this.f ? this | parent(this);
13o = where:occupants(class);
14if (o)
15gas_obj = o[1];
16endif
17endif
18if (valid(gas_obj))
19inc_needed = amount - gas_obj.accumulation;
20if (inc_needed > 0)
21gas_obj:_increase(inc_needed);
22elseif (inc_needed < 0)
23gas_obj:_decrease(-inc_needed);
24endif
25return gas_obj;
26else
27return this:add_to(where, amount);
28endif

entomb

Spec this none thisFlags rxdOwner #361Definer #256

Referenced by

none

Source

1"Copied from generic gas (#57516):recycle by chill (#241405) Wed Jun  2 21:43:18 2010 CDT";
2$heart:unregister(this);
3return pass(@args);