Files
oboe/Blades of Exile/PC.CPP
Chokboyz 84f9d38198 Classic Blades of Exile Beta 2 initial upload.
Changelog (without any order) :

Bug Fixes :

- Giant Strength ability and Skill ability now use the ability strength rather than the item level to calculate effect.
- Won't take damage when moving boats over damaging terrains (fire, cold, magic, poison, disease) anymore.
- Won't take damage when horses refuses to enter a damaging terrain (fire, cold, magic) anymore.
- Horses won't enter damaging terrains (fire, cold, magic) or "horse blocking" terrains when outdoors anymore.
- Boom effects won't be displayed at random places when being damaged outdoors anymore.
- Damage won't be displayed in boom animation when attacking invulnerable monsters, when they are, in fact, unharmed ...
- The first pc won't become active with 0 AP anymore when a pc get killed by backshots.
- Fixed the town loading behavior so that Empties won't appear in Place Town Encounters anymore.
- Cleaned the ressource file (smaller executable).
- Changed the "force place monster" function to preferably flush a summoned monster if flushing is needed. Also prevent a potential infinite loop if trying to force place a monster and all the 60 monsters of a town have a life flag.
- Tweaked exploding arrows firing animation to be smoother (arrow fired, then explosion).
- The spell usable Stinking Cloud ability was protecting against acid instead of the Protection from Acid ability. Fixed.
- The Protection from Disease item ability should now works to the full extent.
- Removed a check on the item graphic when deciding whether to play the"swallow" sound; now checks only for item variety. (Celtic Minstrel)
- Corrected the code so that the party cannot be split again if already split.
- Various messages code cleaning/fixing (Celtic Minstrel)
- Removed the 50 node limit. To prevent infinite loop an interrupt sequence has been implemented (Ctrl-C).
- Cave Bridges battlefield should now appears instead of basic cave floor.
- Wall trims are now working.
- Slowdowns due to trims drawing (animated water, ...) should be fixed now.
- Scenarios in subfolders (under Scenarios/) are now found.
- No more limit for the number of listed scenarios.
- Clicking '?' icon on shopping and talk mode now gives help, even if in 'No instant help' mode.

Changes :

- All terrains and monsters sheets now loaded in memory to bypass storage sheet. That should speed up the game and fix some graphical oddities. Mac and Windows graphics can now be swapped on the fly (i.e without restarting the game). That also removes any graphical limitation in the game.
- In the same way, PC graphics will now be drawn directly to the game gworld.
- You can't end the scenario via a special node if the party is dead anymore (prevent saving an "all dead" party)
- Added a safety check to monsters with Absorb Spells ability to prevent negative health.
- Jobs dialog reimplemented (not useable for now).
- 'Burma Shave' Easter Egg readded.
- Debug Mode : ghost mode implemented.

Classic Scenario Editor Beta 2 :

- Dumping functions won't change current town/outdoor section anymore.
- Finished porting the file IO functions to 32 bits.
- Added a rudimentary custom intro picture behavior : if the intro picture is set to 100, the first icon on the custom sheet will be displayed in the scenario selection menu. Scenario intro pics must be drawn on the same scale as talk icons.
- Whenever the “Place Random Items” function is used, the editor will inform the user that it could not place all items because the town item # limit has been reached, regardless of how many items are actually in the town. That has been fixed (the message now displays only if the max number of items is indeed reached).
- Cleaned the ressources (smaller executable).
- Added a Monster data dumping function (dumps all info about monsters : wandering/special enc/town monsters details ...)
- Added a Specials data dumping function (dumps all info about specials : number, types, variables, ...)
- Town Room/Outdoors Info rectangles are now initialized at ((-1,-1),(-1,-1)) freeing the 0 coordinate and fixing the "Rectangle X" description at (0,0) in the game.
- Cleanse Rectangle SDF1 info rewritten to match actual behavior (0 leave force/fire/webs/crate/barrel, 1 cleans all).
- Corrected the Do SFX Burst info text (1 - telep., 2 - elec.)
- When placing an item with a custom graphic in a town, the editor will display the graphic in the upper-left corner of the space it is placed on. Fixed
- If you edit a monster’s abilities and click Cancel, the ability of that monster will be removed. Fixed.
- If you edit a item's ability, all previously unsaved modifications are erased. Fixed.
- Disappearences of right scroll bar fixed.

Chokboyz

git-svn-id: http://openexile.googlecode.com/svn/trunk@104 4ebdad44-0ea0-11de-aab3-ff745001d230
2009-06-29 15:43:59 +00:00

984 lines
25 KiB
C++

#include "pc.h" // party_record_type
#include "location.h" // location
#include "text.h" // add_string_to_buf
#include "blades.h" // globals
#include "exlsound.h" // play_sound
#include "combat.h" // hit_chance
#include "items.h" // place_item
#include "fields.h" // make_sfx
#include "global.h" // get_ran
#include "infodlgs.h" // give_help
#include "party.h" // adjust_spell_menu
#include "itemdata.h" // return_dummy_item
#include "locutils.h" // is_container
#include "globvar.h"
void pc_record_type::kill(short type)
{
short i = 24;
bool dummy, no_save = false;
location item_loc;
if (type >= 10)
{
type -= 10;
no_save = true;
}
if (type != 4)
i = hasAbilEquip(48); //check if has life saving items
else
i = hasAbilEquip(49); //check if has protection vs petrification items
short which_pc = getNum();
if ((no_save == false) && (type != 0) && (skills[SKILL_LUCK] > 0) &&
(get_ran(1,0,100) < hit_chance[skills[SKILL_LUCK]])) {
add_string_to_buf(" But you luck out! ");
cur_health = 0;
}
else if ((i == 24) || (type == 0)) {
if (combat_active_pc == which_pc)
combat_active_pc = 6;
for (i = 0; i < 24; i++)
equip[i] = FALSE;
item_loc = (overall_mode >= MODE_COMBAT) ? pc_pos[which_pc] : c_town.p_loc;
if (type == 2)
make_sfx(item_loc.x,item_loc.y,3);
else if (type == 3)
make_sfx(item_loc.x,item_loc.y,6);
if (overall_mode != 0)
for (i = 0; i < 24; i++)
if (items[i].variety != 0) {
dummy = place_item(items[i],item_loc,TRUE);
items[i].variety = 0;
}
if ((type == 2) || (type == 3))
play_sound(21);
if(type == 4){
play_sound(43);
sprintf ((char *) create_line, " %s is turned to stone. ",(char *) name);
add_string_to_buf((char *) create_line);
}
main_status = type;
pc_moves[which_pc] = 0;
}
else {
if (type == 4) {
sprintf ((char *) create_line, " %s is immuned to petrification. ",(char *) name);
add_string_to_buf((char*) create_line); //inform of what has happened
}
else{
add_string_to_buf(" Life saved! ");
takeItem(i);
heal(200);
}
}
current_pc = first_active_pc();
if (current_pc > 5) {
for (i = 0; i < NUM_OF_PCS; i++)
if (adven[i].status > 0)
current_pc = i;
}
put_pc_screen();
set_stat_window(current_pc);
}
bool pc_record_type::runTrap(short trap_type, short trap_level, short diff)
{
short r1,skill,i,num_hits = 1,i_level;
short trap_odds[30] = {5,30,35,42,48, 55,63,69,75,77,
78,80,82,84,86, 88,90,92,94,96,98,99,99,99,99,99,99,99,99,99};
num_hits += trap_level;
if (trap_type == TRAP_RANDOM)
trap_type = get_ran(1,1,4);
/// ??? => no trap after all ;)
if (trap_type == 6)
return true;
i = statAdj(1);
if ((i_level = getProtLevel(42)) > 0)
i += i_level / 2;
skill = minmax(0, 20, skills[14] + skills[SKILL_LUCK] / 2 + 1 - c_town.difficulty + 2 * i);
r1 = get_ran(1,0,100) + diff;
// Nimble?
if (traits[TRAIT_NIMBLE] == TRUE) r1 -= 6;
if (r1 < trap_odds[skill])
{
add_string_to_buf(" Trap disarmed. ");
return true;
}
else add_string_to_buf(" Disarm failed. ");
switch (trap_type)
{
case TRAP_BLADE:
for (i = 0; i < num_hits; i++)
{
add_string_to_buf(" A knife flies out! ");
damage(get_ran(2 + c_town.difficulty / 14,1,10),DAMAGE_WEAPON,-1);
}
break;
case TRAP_DART:
add_string_to_buf(" A dart flies out. ");
poison((3 + c_town.difficulty / 14) + (trap_level * 2));
break;
case TRAP_GAS:
add_string_to_buf(" Poison gas pours out. ");
adven.poison((2 + c_town.difficulty / 14) + trap_level * 2);
break;
case TRAP_EXPLOSION:
for (i = 0; i < num_hits; i++)
{
add_string_to_buf(" There is an explosion. ");
adven.damage(get_ran(3 + c_town.difficulty / 13,1,8), DAMAGE_FIRE);
}
break;
case TRAP_SLEEP_RAY:
add_string_to_buf(" A purple ray flies out. ");
sleep((200 + c_town.difficulty * 100) + (trap_level * 400),12,50);
break;
case TRAP_DRAIN_XP:
add_string_to_buf(" You feel weak. ");
experience = max(0, experience - (40 + trap_level * 30));
break;
case TRAP_ALERT:
add_string_to_buf(" An alarm goes off!!! ");
make_town_hostile();
break;
case TRAP_FLAMES:
add_string_to_buf(" Flames shoot from the walls. ");
adven.damage(get_ran(10 + trap_level * 5,1,8),DAMAGE_FIRE);
break;
case TRAP_DUMBFOUND:
add_string_to_buf(" You feel disoriented. ");
adven.dumbfound(2 + trap_level * 2);
break;
case TRAP_DISEASE:
add_string_to_buf(" You prick your finger. ");
disease((3 + c_town.difficulty / 14) + (trap_level * 2));
break;
case TRAP_DISEASE_ALL:
add_string_to_buf(" A foul substance sprays out.");
adven.disease((2 + c_town.difficulty / 14) + (trap_level * 2));
break;
default:
add_string_to_buf(" (ERROR: Unknown type of trap!)");
break;
}
put_pc_screen();
put_item_screen(stat_window,0);
return true;
}
short pc_record_type::statAdj(short which)
{
short tr;
tr = skill_bonus[skills[which]];
if (which == 2) {
if (traits[1] == TRUE) tr++;
if (hasAbilEquip(40) < 24) tr++;
}
if (which == 0)
if (traits[8] == TRUE) tr++;
if (hasAbilEquip(38) < 24)
tr++;
if (which == 1) {
if (hasAbilEquip(39) < 24)
tr++;
}
return tr;
}
void pc_record_type::giveXP(short amt)
{
short adjust,add_hp;
short xp_percent[30] = {150,120,100,90,80,70,60,50,50,50,
45,40,40,40,40,35,30,25,23,20,
15,15,15,15,15,15,15,15,15,15};
if (!isAlive()) return;
if (level > 49)
{
level = 50;
return;
}
if (amt > 200) { // debug
MessageBeep(MB_OK);
ASB("Oops! Too much xp!");
ASB("Report this!");
return;
}
if (amt < 0) { // debug
MessageBeep(MB_OK);
ASB("Oops! Negative xp!");
ASB("Report this!");
return;
}
if (level >= 40) adjust = 15;
else adjust = xp_percent[level / 2];
if ((amt > 0) && (level > 7))
{
if (get_ran(1,0,100) < xp_percent[level / 2]) amt--;
}
if (amt <= 0) return;
experience += (max(((amt * adjust) / 100), 0) * 100) / 100;
party.total_xp_gained += (max(((amt * adjust) / 100), 0) * 100) / 100;
if (experience < 0) {
MessageBeep(MB_OK);
ASB("Oops! Xp became negative somehow!");
ASB("Report this!");
experience = level * (get_tnl(this)) - 1;
return;
}
if (experience > 15000)
{
experience = 15000;
return;
}
while (experience >= (level * (get_tnl(this))))
{
play_sound(7);
level++;
sprintf ((char *) c_line, " %s is level %d! ",(char *) name, level);
add_string_to_buf((char *) c_line);
skill_pts += (level < 20) ? 5 : 4;
add_hp = (level < 26) ? get_ran(1,2,6) + skill_bonus[skills[0]]
: max (skill_bonus[skills[0]],0);
if (add_hp < 0) add_hp = 0;
max_health += add_hp;
if (max_health > 250) max_health = 250;
cur_health += add_hp;
if (cur_health > 250) cur_health = 250;
put_pc_screen();
}
}
void pc_record_type::drainXP(short how_much)
{
if (!isAlive()) return;
experience = max(experience - how_much, 0);
sprintf ((char *) c_line, " %s drained.",(char *) name);
add_string_to_buf((char *) c_line);
}
void pc_record_type::restoreSP(short amt)
{
if (!isAlive()) return;
if (cur_sp > max_sp) return;
cur_sp += amt;
if (cur_sp > max_sp) cur_sp = max_sp;
}
void pc_record_type::cure(short amt)
{
if (!isAlive()) return;
if (status[STATUS_POISON] <= amt)
status[STATUS_POISON] = 0;
else
status[STATUS_POISON] -= amt;
one_sound(51);
}
void pc_record_type::curse(short how_much)
{
if (!isAlive()) return;
status[STATUS_BLESS] = max(status[STATUS_BLESS] - how_much, -8);
sprintf ((char *) c_line, " %s cursed.",(char *) name);
add_string_to_buf((char *) c_line);
put_pc_screen();
give_help(59,0,0);
}
void pc_record_type::dumbfound(short how_much)
{
short r1;
if (!isAlive()) return;
r1 = get_ran(1,0,90);
if (hasAbilEquip(53) < 24) {
add_string_to_buf(" Ring of Will glows.");
r1 -= 10;
}
if (r1 < level)
how_much -= 2;
if (how_much <= 0) {
sprintf ((char *) c_line, " %s saved.",(char *) name);
add_string_to_buf((char *) c_line);
return;
}
status[STATUS_DUMB] = min(status[STATUS_DUMB] + how_much, 8);
sprintf ((char *) c_line, " %s dumbfounded.",(char *) name);
add_string_to_buf((char *) c_line);
one_sound(67);
put_pc_screen();
adjust_spell_menus();
give_help(28,0,0);
}
void pc_record_type::disease(short how_much)
{
short r1, tlevel;
if (!isAlive()) return;
r1 = get_ran(1,0,100);
if (r1 < level * 2)
how_much -= 2;
if (how_much <= 0)
{
sprintf ((char *) c_line, " %s saved.",(char *) name);
add_string_to_buf((char *) c_line);
return;
}
if ((tlevel = getProtLevel(62)) > 0)
how_much -= tlevel / 2;
if ((traits[12] == TRUE) && (how_much > 1)) how_much++;
if ((traits[12] == TRUE) && (how_much == 1) && (get_ran(1,0,1) == 0)) how_much++;
status[STATUS_DISEASE] = min(status[STATUS_DISEASE] + how_much,8);
sprintf ((char *) c_line, " %s diseased.",(char *) name);
add_string_to_buf((char *) c_line);
one_sound(66);
put_pc_screen();
give_help(29,0,0);
}
void pc_record_type::sleep(short how_much,short what_type,short adjust)
// higher adjust, less chance of saving
{
short r1, tlevel;
if (!isAlive()) return;
if (how_much == 0)
return;
if ((what_type == STATUS_ASLEEP) || (what_type == STATUS_PARALYZED)) { ////
if ((tlevel = getProtLevel(53)) > 0)
how_much -= tlevel / 2;
if ((tlevel = getProtLevel(54)) > 0)
how_much -= (what_type == STATUS_ASLEEP) ? tlevel : tlevel * 300;
}
r1 = get_ran(1,0,100) + adjust;
if (r1 < 30 + level * 2)
how_much = -1;
if ((what_type == STATUS_ASLEEP) && ((traits[7] > 0) || (status[STATUS_ASLEEP] < 0)))
how_much = -1;
if (how_much <= 0) {
sprintf ((char *) c_line, " %s resisted.",(char *) name);
add_string_to_buf((char *) c_line);
return;
}
if (isAlive()) {
status[what_type] = how_much;
if (what_type == STATUS_ASLEEP)
sprintf ((char *) c_line, " %s falls asleep.",(char *) name);
else sprintf ((char *) c_line, " %s paralyzed.",(char *) name);
if (what_type == STATUS_ASLEEP)
play_sound(96);
else play_sound(90);
add_string_to_buf((char *) c_line);
pc_moves[getNum()] = 0;
}
put_pc_screen();
if (what_type == STATUS_ASLEEP)
give_help(30,0,0);
else give_help(32,0,0);
}
void pc_record_type::slow(short how_much)
{
if (!isAlive()) return;
status[STATUS_HASTE] = minmax(-8,8,status[STATUS_HASTE] - how_much);
if (how_much < 0)
sprintf ((char *) c_line, " %s hasted.",(char *) name);
else sprintf ((char *) c_line, " %s slowed.",(char *) name);
add_string_to_buf((char *) c_line);
put_pc_screen();
if (how_much < 0)
give_help(35,0,0);
}
void pc_record_type::web(short how_much)
{
if (!isAlive()) return;
status[STATUS_WEBS] = min(status[STATUS_WEBS] + how_much,8);
sprintf ((char *) c_line, " %s webbed.",(char *) name);
add_string_to_buf((char *) c_line);
one_sound(17);
put_pc_screen();
give_help(31,0,0);
}
void pc_record_type::acid(short how_much)
{
if (!isAlive()) return;
if (hasAbilEquip(36) < 24) {
sprintf ((char *) c_line, " %s resists acid.",(char *) name);
add_string_to_buf((char *) c_line);
return;
}
status[STATUS_ACID] += how_much;
sprintf ((char *) c_line, " %s covered with acid!",(char *) name);
add_string_to_buf((char *) c_line);
one_sound(42);
put_pc_screen();
}
void pc_record_type::heal(short amt)
{
if (!isAlive()) return;
if (cur_health > max_health) return;
cur_health += amt;
if (cur_health > max_health)
cur_health = max_health;
}
void pc_record_type::sortItems()
{
item_record_type store_item;
short item_priority[26] = {20,8,8,20,9, 9,3,2,1,0, 7,20,10,10,10, 10,10,10,5,6, 4,11,12,9,9, 9};
bool no_swaps = false, store_equip;
int i;
while (no_swaps == false) {
no_swaps = true;
for (i = 0; i < 23; i++)
if (item_priority[items[i + 1].variety] <
item_priority[items[i].variety]) {
no_swaps = false;
store_item = items[i + 1];
items[i + 1] = items[i];
items[i] = store_item;
store_equip = equip[i + 1];
equip[i + 1] = equip[i];
equip[i] = store_equip;
if (weap_poisoned == i + 1)
weap_poisoned--;
else if (weap_poisoned == i)
weap_poisoned++;
}
}
}
short pc_record_type::getNum()
{
short i;
for (i = 0; i < NUM_OF_PCS; i++)
{
if (&adven[i] == this) break;;
}
return i;
}
bool pc_record_type::giveToPC(item_record_type item, bool print_result)
{
short free_space;
char announce_string[60];
if (item.variety == 0)
return true;
if (item.variety == 3) {
party.gold += item.item_level;
ASB("You get some gold.");
return true;
}
if (item.variety == 11) {
party.food += item.item_level;
ASB("You get some food.");
return true;
}
if (item_weight(item) > amountCanCarry() - amountCarried()) {
if (print_result == true) {
MessageBeep(MB_OK);
ASB("Item too heavy to carry.");
}
return false;
}
if (((free_space = hasSpace()) == 24) || (!isAlive()))
return false;
else {
item.item_properties = item.item_properties & 253; // not property
item.item_properties = item.item_properties & 247; // not contained
items[free_space] = item;
if (print_result == 1) {
if (stat_window == getNum())
put_item_screen(stat_window,0);
}
if (in_startup_mode == FALSE) {
if (item.isIdent() == false)
sprintf((char *) announce_string," %s gets %s.",name,item.name);
else sprintf((char *) announce_string," %s gets %s.",name,item.full_name);
if (print_result)
add_string_to_buf((char *)announce_string);
}
combineThings();
sortItems();
return true;
}
return false;
}
// returnes equipped protection level of specified abil, or -1 if no such abil is equipped
short pc_record_type::getProtLevel(short abil)
{
for (int i = 0; i < 24; i++)
if ((items[i].variety != 0) && (items[i].ability == abil) && (equip[i] == TRUE))
return items[i].ability_strength;
return (-1);
}
short pc_record_type::hasAbilEquip(short abil)
{
short i = 0;
while (((items[i].variety == 0) || (items[i].ability != abil)
|| (equip[i] == FALSE)) && (i < 24))
i++;
return i;
}
short pc_record_type::hasAbil(short abil)
{
short i = 0;
while (((items[i].variety == 0) || (items[i].ability != abil)) && (i < 24)) i++;
return i;
}
short pc_record_type::amountCanCarry()
{
return 100 + (15 * min(skills[0],20)) + ((traits[8] == 0) ? 0 : 30)
+ ((traits[14] == 0) ? 0 : -50);
}
short pc_record_type::amountCarried()
{
short i, storage = 0;
bool airy = false, heavy = false;
for (i = 0; i < 24; i++)
if (items[i].variety > 0)
{
storage += item_weight(items[i]);
if (items[i].ability == 44) airy = true;
if (items[i].ability == 45) heavy = true;
}
if (airy) storage -= 30;
if (heavy) storage += 30;
if (storage < 0) storage = 0;
return storage;
}
short pc_record_type::hasSpace()
{
int i = 0;
while (i < 24)
{
if (items[i].variety == 0)
return i;
i++;
}
return 24;
}
// returns 1 if OK, 2 if no room, 3 if not enough cash, 4 if too heavy, 5 if too many of item
short pc_record_type::okToBuy(short cost, item_record_type item)
{
int i;
if ((item.variety != 3) && (item.variety != 11)) {
for (i = 0; i < 24; i++)
if ((items[i].variety > 0) && (items[i].type_flag == item.type_flag)
&& (items[i].charges > 123))
return 5;
if (hasSpace() == 24) return 2;
if (item_weight(item) > amountCanCarry() - amountCarried()) return 4;
}
if (party.takeGold(cost, false) == false)
return 3;
return 1;
}
void pc_record_type::takeItem(short which_item)
//short pc_num,which_item; // if which_item > 30, don't update stat win, item is which_item - 30
{
int i;
bool do_print = true;
if (which_item >= 30) {
do_print = false;
which_item -= 30;
}
if ((weap_poisoned == which_item) && (status[0] > 0)) {
add_string_to_buf(" Poison lost. ");
status[0] = 0;
}
if ((weap_poisoned > which_item) && (status[0] > 0))
weap_poisoned--;
for (i = which_item; i < 23; i++) {
items[i] = items[i + 1];
equip[i] = equip[i + 1];
}
items[23] = return_dummy_item();
equip[23] = FALSE;
if ((stat_window == getNum()) && (do_print))
put_item_screen(stat_window,1);
}
void pc_record_type::removeCharge(short which_item)
{
if (items[which_item].charges > 0)
{
items[which_item].charges--;
if (items[which_item].charges == 0) takeItem(which_item);
}
if (stat_window == getNum())
put_item_screen(stat_window,1);
}
void pc_record_type::enchantWeapon(short item_hit, short enchant_type, short new_val)
{
char store_name[60];
if ((items[item_hit].isMagic()) || (items[item_hit].ability != 0)) return;
items[item_hit].item_properties |= 4;
switch (enchant_type) {
case 0:
sprintf((char *)store_name,"%s (+1)", items[item_hit].full_name);
items[item_hit].bonus++;
items[item_hit].value = new_val;
break;
case 1:
sprintf((char *)store_name,"%s (+2)", items[item_hit].full_name);
items[item_hit].bonus += 2;
items[item_hit].value = new_val;
break;
case 2:
sprintf((char *)store_name,"%s (+3)", items[item_hit].full_name);
items[item_hit].bonus += 3;
items[item_hit].value = new_val;
break;
case 3:
sprintf((char *)store_name,"%s (F)", items[item_hit].full_name);
items[item_hit].ability = 110;
items[item_hit].ability_strength = 5;
items[item_hit].charges = 8;
break;
case 4:
sprintf((char *)store_name,"%s (F!)", items[item_hit].full_name);
items[item_hit].value = new_val;
items[item_hit].ability = 1;
items[item_hit].ability_strength = 5;
break;
case 5:
sprintf((char *)store_name,"%s (+5)", items[item_hit].full_name);
items[item_hit].value = new_val;
items[item_hit].bonus += 5;
break;
case 6:
sprintf((char *)store_name,"%s (B)", items[item_hit].full_name);
items[item_hit].bonus++;
items[item_hit].ability = 71;
items[item_hit].ability_strength = 5;
items[item_hit].magic_use_type = 0;
items[item_hit].charges = 8;
break;
default:
strcpy(store_name, items[item_hit].full_name);
break;
}
if (items[item_hit].value > 15000)
items[item_hit].value = 15000;
if (items[item_hit].value < 0)
items[item_hit].value = 15000;
strcpy(items[item_hit].full_name,store_name);
}
void pc_record_type::equipItem(short item_num)
{
short num_equipped_of_this_type = 0;
short num_hands_occupied = 0;
short i;
short equip_item_type = 0;
if ((overall_mode == MODE_COMBAT) && (items[item_num].variety == 11))
add_string_to_buf("Equip: Not in combat");
else {
// unequip
if (equip[item_num] == TRUE) {
if ((equip[item_num] == TRUE) &&
(items[item_num].isCursed()))
add_string_to_buf("Equip: Item is cursed. ");
else {
equip[item_num] = FALSE;
add_string_to_buf("Equip: Unequipped");
if ((weap_poisoned == item_num) && (status[0] > 0)) {
add_string_to_buf(" Poison lost. ");
status[0] = 0;
}
}
}
else { // equip
if (equippable[items[item_num].variety] == FALSE)
add_string_to_buf("Equip: Can't equip this item.");
else {
for (i = 0; i < 24; i++)
if (equip[i] == TRUE) {
if (items[i].variety == items[item_num].variety)
num_equipped_of_this_type++;
num_hands_occupied = num_hands_occupied + num_hands_to_use[items[i].variety];
}
equip_item_type = excluding_types[items[item_num].variety];
// Now if missile is already equipped, no more missiles
if (equip_item_type > 0) {
for (i = 0; i < 24; i++)
if ((equip[i] == TRUE) && (excluding_types[items[i].variety] == equip_item_type)) {
add_string_to_buf("Equip: You have something of");
add_string_to_buf(" this type equipped.");
return;
}
}
if ((is_combat()) && (items[item_num].variety == 13))
add_string_to_buf("Equip: Not armor in combat");
else if ((2 - num_hands_occupied) < num_hands_to_use[items[item_num].variety])
add_string_to_buf("Equip: Not enough free hands");
else if (num_that_can_equip[items[item_num].variety] <= num_equipped_of_this_type)
add_string_to_buf("Equip: Can't equip another");
else {
equip[item_num] = TRUE;
add_string_to_buf("Equip: OK");
}
}
}
}
if (stat_window == getNum())
put_item_screen(stat_window,1);
}
void pc_record_type::dropItem(short item_num, location where_drop)
{
short choice, how_many = 0;
item_record_type item_store;
bool take_given_item = true;
location loc;
item_store = items[item_num];
if ((equip[item_num] == TRUE) && (items[item_num].isCursed()))
add_string_to_buf("Drop: Item is cursed. ");
else switch (overall_mode) {
case 0:
choice = fancy_choice_dialog(1093,0);
if (choice == 1)
return;
add_string_to_buf("Drop: OK");
if ((item_store.type_flag > 0) && (item_store.charges > 1)) {
how_many = get_num_of_items(item_store.charges);
if (how_many == item_store.charges)
takeItem(item_num);
else items[item_num].charges -= how_many;
}
else takeItem(item_num);
break;
case 5: case 15:
loc = where_drop;
if ((item_store.type_flag > 0) && (item_store.charges > 1)) {
how_many = get_num_of_items(item_store.charges);
if (how_many <= 0)
return;
if (how_many < item_store.charges)
take_given_item = false;
item_store.charges = how_many;
}
if (is_container(loc) == TRUE)
item_store.item_properties = item_store.item_properties | 8;
if (place_item(item_store,loc,FALSE) == FALSE) {
add_string_to_buf("Drop: Too many items on ground");
item_store.item_properties = item_store.item_properties & 247; // not contained
}
else {
if (item_store.isContained())
add_string_to_buf("Drop: Item put away");
else add_string_to_buf("Drop: OK");
items[item_num].charges -= how_many;
if (take_given_item) takeItem(item_num);
}
break;
}
}
void pc_record_type::giveThing(short item_num)
{
short who_to,how_many = 0;
item_record_type item_store;
bool take_given_item = true;
short pc_num = getNum();
if ((equip[item_num] == TRUE) && (items[item_num].isCursed()))
add_string_to_buf("Give: Item is cursed. ");
else {
item_store = items[item_num];
who_to = char_select_pc(1,1,"Give item to who?");
if ((overall_mode == MODE_COMBAT) && (adjacent(pc_pos[pc_num],pc_pos[who_to]) == FALSE)) {
add_string_to_buf("Give: Must be adjacent.");
who_to = 6;
}
if ((who_to < 6) && (who_to != pc_num)
&& ((overall_mode != MODE_COMBAT) || (adjacent(pc_pos[pc_num],pc_pos[who_to]) == TRUE))) {
if ((item_store.type_flag > 0) && (item_store.charges > 1)) {
how_many = get_num_of_items(item_store.charges);
if (how_many == 0)
return;
if (how_many < item_store.charges)
take_given_item = false;
items[item_num].charges -= how_many;
item_store.charges = how_many;
}
if (adven[who_to].giveToPC(item_store,0) == true) {
if (take_given_item) takeItem(item_num);
}
else {
if (adven[who_to].hasSpace() == 24)
ASB("Can't give: PC has max. # of items.");
else ASB("Can't give: PC carrying too much.");
if (how_many > 0)
items[item_num].charges += how_many;
}
}
}
}
void pc_record_type::combineThings()
{
int i,j,test;
for (i = 0; i < 24; i++) {
if ((items[i].variety > 0) && (items[i].type_flag > 0) && (items[i].isIdent()))
{
for (j = i + 1; j < 24; j++)
if ((items[j].variety > 0) && (items[j].type_flag == items[i].type_flag) && (items[j].isIdent()))
{
add_string_to_buf("(items combined)");
test = items[i].charges + items[j].charges;
if (test > 125) {
items[i].charges = 125;
ASB("(Can have at most 125 of any item.");
}
else items[i].charges += items[j].charges;
if (equip[j] == TRUE) {
equip[i] = TRUE;
equip[j] = FALSE;
}
takeItem(30 + j);
}
}
if ((items[i].variety > 0) && (items[i].charges < 0))
items[i].charges = 1;
}
}