/* -*- LPC -*- */
#include <weather.h>
#include <clothing.h>
#include <playtesters.h>
#define COMFORTABLE 20
#define ABS(x) (x > 0? x : -x)
string disp_warmth(int, int);
string disp_total(int i);
int cmd(string str) {
object where, *clothes, item;
string zone, type, *zones, tmp;
mixed types;
int adjustment, correction, temperature, room_temp, *enums, cwarm, ccool;
where = environment(this_player());
if(!where)
return notify_fail("You have no environment.\n");
// If they're on a horse or somesuch then use that locations temperature
// info.
if(!where->query_property("location") &&
environment(where) &&
environment(where)->query_property("location")) {
where = environment(where);
}
// Figure out the temperature where we are.
switch(where->query_property("location")) {
case "outside":
room_temp = (WEATHER->query_temperature(where) - COMFORTABLE);
break;
default:
room_temp = 0;
}
temperature = this_player()->query_personal_temp();
// set the warmth of the room.
room_temp += where->query_property("warmth");
room_temp -= where->query_property("cooling");
write(sprintf("It's %s here.\n",
WEATHER->temp_string(room_temp + COMFORTABLE)));
// Calculate how warm (or cool) their clothing is keeping them.
clothes = filter_array(this_player()->query_wearing(),
(: !$1->id("scabbard") &&
!$1->id("belt") &&
!$1->id("backpack") &&
!$1->id("glasses") &&
!$1->id("jewellery") :));
zones = ({ });
foreach(item in clothes) {
types = item->query_type();
if(!arrayp(types)) {
types = ({ item->query_type() });
}
ccool = 0;
cwarm = 0;
foreach(type in types) {
// Find out what zone this clothing type covers.
// If it doesn't cover a zone (eg. jewellery) it doesn't give any
// warmth.
foreach(zone in CLOTHING_HANDLER->query_zone_names(type)) {
if(member_array(zone, zones) == -1)
zones += ({ zone });
if(item->query_property("warmth")) {
adjustment += item->query_property("warmth");
cwarm += item->query_property("warmth");
} else {
adjustment++;
cwarm++;
}
// If it's warm here then do adjustments for clothing that
// cool you.
if(room_temp > 0 && item->query_property("cooling")) {
adjustment -= item->query_property("cooling");
ccool += item->query_property("cooling");
}
}
}
tmp = item->query_name();
if(cwarm && ccool) {
write(sprintf("Your %s provide%s %s and %s.\n", item->query_short(),
(tmp[<1] == 's' && tmp[<2 .. <1] != "ss") ? "" : "s",
disp_warmth(cwarm, 1),
disp_warmth(ccool, 0)));
} else if(cwarm) {
write(sprintf("Your %s provide%s %s.\n", item->query_short(),
(tmp[<1] == 's' && tmp[<2 .. <1] != "ss") ? "" : "s",
disp_warmth(cwarm, 1)));
} else if(ccool) {
write(sprintf("Your %s provide%s %s.\n", item->query_short(),
(tmp[<1] == 's' && tmp[<2 .. <1] != "ss") ? "" : "s",
disp_warmth(ccool, 0)));
}
}
// You get a warmth bonus or coolness bonus for each zone covered.
// This means it's better to cover more of your body when it's cold.
// It also means you can wear light clothing with less temperature
// penalties since the warmth & cooling cancel out somewhat.
if(room_temp < 0) {
adjustment += sizeof(zones);
if(room_temp + sizeof(zones) > 5)
adjustment -= (room_temp + sizeof(zones) - 5);
} else {
adjustment -= sizeof(zones);
if(room_temp - sizeof(zones) < -5)
adjustment -= (room_temp - sizeof(zones) + 5);
}
// Wetness makes you cooler -- so sweating isn't necessarily a bad thing.
ccool = 0;
enums = (int *)this_player()->effects_matching("body.wetness");
if ( sizeof( enums ) ) {
adjustment -= sqrt(sqrt((int)this_player()->arg_of( enums[ 0 ] ))) * 2;
ccool = sqrt(sqrt((int)this_player()->arg_of( enums[ 0 ] ))) * 2;
}
// add their personal warmth (from effects or shadows)
adjustment += this_player()->query_property("warmth");
adjustment -= this_player()->query_property("cooling");
// this hopefully it does two things.
// 1. effectively puts a maximum/minimum on temperature
// 2. accounts for the body working to adjust temperature.
if(temperature > room_temp && room_temp >= 0 || temperature > 5)
correction -= (temperature / 5) + 5;
if(temperature < room_temp && room_temp <= 0 || temperature < -5)
correction -= (temperature / 5) - 5;
write(sprintf("On balance, you are %s and %s.\n",
this_player()->query_temp_str(),
disp_total(to_int((room_temp+adjustment + correction)))));
return 1;
}
string disp_warmth(int i, int warm) {
string pos, neg;
if(warm) {
pos = " warmth";
neg = " cooling";
} else {
pos = " cooling";
neg = " warmth";
}
switch(i) {
case -1000..-19: return "an enormous amount of"+neg;
case -9..-18: return "a lot of"+neg;
case -8..-4: return "quite a lot of"+neg;
case -3..-2: return "some"+neg;
case -1: return "a bit of"+neg;
case 0: return "no"+pos;
case 1: return "a bit of"+pos;
case 2..3: return "some"+pos;
case 4..8: return "quite a lot of"+pos;
case 9..18: return "a lot of"+pos;
default: return "an enormous amount of"+pos;
}
}
string disp_total(int i) {
switch(i) {
case -1000..-51: return "are freezing fast";
case -50..-21: return "are cooling down quickly";
case -20..-11: return "are cooling down";
case -10..-6: return "are cooling down slowly";
case -5..5: return "will stay pretty much as you are";
case 6..10: return "are warming up slowly";
case 11..20: return "are warming up";
case 21..50: return "are warming up quickly";
case 51..1000: return "are cooking rapidly";
default:
return "broken: " + i + "\n";
}
}
mixed *query_patterns() {
return ({ "", (: cmd("") :) });
}