Stuff about force cages, stone blocks, move mountains

- Add all objects, fields, and sfx to place_spell_pattern
- Add move mountains effect to place_spell_pattern
- Most of the implementation for force cages and stone blocks is now done (still untested)
- Properly implement MOVE_MOUNTAINS_MASS spell
This commit is contained in:
2014-12-14 15:21:53 -05:00
parent c8889a9989
commit fbe186f8b7
9 changed files with 174 additions and 21 deletions

View File

@@ -2946,6 +2946,11 @@ bool town_move_party(location destination,short forced)////
ter_num_t ter;
bool check_f = false;
if(univ.town.is_force_cage(univ.town.p_loc.x, univ.town.p_loc.y)) {
add_string_to_buf("Move: Can't escape.");
return false;
}
if (in_scen_debug && ghost_mode)
forced = true;

View File

@@ -420,7 +420,14 @@ bool pc_combat_move(location destination) ////
location monst_loc,store_loc;
short spec_num;
if (monst_there(destination) > univ.town->max_monst())
monst_hit = monst_there(destination);
if(monst_hit > univ.town->max_monst() && univ.party[current_pc].status[eStatus::FORCECAGE] > 0) {
add_string_to_buf("Move: Can't escape.");
return false;
}
if(monst_hit > univ.town->max_monst())
keep_going = check_special_terrain(destination,eSpecCtx::COMBAT_MOVE,current_pc,&spec_num,&check_f);
if (check_f == true)
forced = true;
@@ -451,7 +458,7 @@ bool pc_combat_move(location destination) ////
add_string_to_buf(create_line);
return true;
}
else if ((monst_hit = monst_there(destination)) <= univ.town->max_monst()) {
else if(monst_hit <= univ.town->max_monst()) {
// s2 = 2 here appears to mean "go ahead and attack", while s2 = 1 means "cancel attack".
// Then s1 % 2 == 1 means the monster is hostile to the party.
s1 = univ.town.monst[monst_hit].attitude;
@@ -3734,6 +3741,45 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho
case CLOUD_SLEEP:
sleep_cloud_space(i,j);
break;
case FIELD_SMASH:
crumble_wall(loc(i,j));
break;
case OBJECT_CRATE:
univ.town.set_crate(i,j,true);
break;
case OBJECT_BARREL:
univ.town.set_barrel(i,j,true);
break;
case OBJECT_BLOCK:
univ.town.set_block(i,j,true);
break;
case BARRIER_CAGE:
univ.town.set_force_cage(i, j, true);
break;
case SFX_SMALL_BLOOD:
univ.town.set_sm_blood(i,j,true);
break;
case SFX_MEDIUM_BLOOD:
univ.town.set_med_blood(i,j,true);
break;
case SFX_LARGE_BLOOD:
univ.town.set_lg_blood(i,j,true);
break;
case SFX_SMALL_SLIME:
univ.town.set_sm_slime(i,j,true);
break;
case SFX_LARGE_SLIME:
univ.town.set_lg_slime(i,j,true);
break;
case SFX_ASH:
univ.town.set_ash(i,j,true);
break;
case SFX_BONES:
univ.town.set_bones(i,j,true);
break;
case SFX_RUBBLE:
univ.town.set_rubble(i,j,true);
break;
}
}
draw_terrain(0);
@@ -3767,6 +3813,13 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho
r1 = get_ran(4,1,8);
damage_pc(k,r1,DAMAGE_WEAPON,eRace::UNKNOWN,0);
break;
case OBJECT_BLOCK:
r1 = get_ran(6,1,8);
damage_pc(k,r1,DAMAGE_WEAPON,eRace::UNKNOWN,0);
break;
case BARRIER_CAGE:
univ.party[k].status[eStatus::FORCECAGE] = 8;
break;
default:
eDamageType type = DAMAGE_MARKED;
unsigned short dice;
@@ -3856,6 +3909,13 @@ static void place_spell_pattern(effect_pat_type pat,location center,unsigned sho
which_m = &univ.town.monst[k];
charm_monst(which_m,0,eStatus::ASLEEP,3);
break;
case OBJECT_BLOCK:
r1 = get_ran(6,1,8);
damage_monst(k,who_hit,r1,0,DAMAGE_WEAPON,0);
break;
case BARRIER_CAGE:
univ.town.monst[k].status[eStatus::FORCECAGE] = 8;
break;
default:
eDamageType type = DAMAGE_MARKED;
unsigned short dice;
@@ -4188,8 +4248,12 @@ bool hit_end_c_button()
if (which_combat_type == 0) {
end_ok = out_monst_all_dead();
}
// if (univ.party[0].extra[7] > 0)
// end_ok = true;
for(int i = 0; i < 6; i++) {
if(univ.party[i].status[eStatus::FORCECAGE] > 0) {
add_string_to_buf(" Someone trapped.");
return false;
}
}
if (end_ok == true)
end_combat();
@@ -4695,6 +4759,33 @@ void spell_cast_hit_return()
}
}
static void process_force_cage(location loc, short i) {
if(i >= 100) {
short m = i - 100;
cCreature& which_m = univ.town.monst[m];
if(which_m.attitude % 2 == 1 && get_ran(1,1,100) < which_m.mu * 10 + which_m.cl * 4 + 5) {
play_sound(60);
monst_spell_note(m, 50);
univ.town.set_force_cage(loc.x,loc.y,false);
which_m.status[eStatus::FORCECAGE] = 0;
} else which_m.status[eStatus::FORCECAGE] = 8;
} else if(i < 0) {
if(get_ran(1,1,100) < 35)
univ.town.set_force_cage(loc.x,loc.y,false);
} else if(i < 6) {
cPlayer& who = univ.party[i];
// We want to make sure everyone has a chance of eventually breaking a cage, because it never ends on its own,
// and because being trapped unconditionally prevents you from ending combat mode.
short bonus = 5 + who.skills[eSkill::MAGE_LORE];
if(get_ran(1,1,100) < who.skills[eSkill::MAGE_SPELLS]*10 + who.skills[eSkill::PRIEST_SPELLS]*4 + bonus) {
play_sound(60);
add_string_to_buf(" " + who.name + " breaks force cage.");
univ.town.set_force_cage(loc.x,loc.y,false);
who.status[eStatus::FORCECAGE] = 0;
} else who.status[eStatus::FORCECAGE] = 8;
}
}
void process_fields()
{
short i,j,k,r1;
@@ -4791,6 +4882,15 @@ void process_fields()
if (r1 == 1)
univ.town.set_blade_wall(i,j,false);
}
if(univ.town.is_force_cage(i,j)) {
loc.x = i; loc.y = j;
short m = monst_there(loc);
if(m == 90) {
short pc = pc_there(loc);
if(pc == 6) process_force_cage(loc, -1);
else process_force_cage(loc, pc);
} else process_force_cage(loc, 100 + m);
}
}
processing_fields = false;

View File

@@ -22,15 +22,6 @@
#define NUM_OF_BOATS 30
#define NUM_OF_HORSES 30
#define SFX_SMALL_BLOOD 1
#define SFX_MEDIUM_BLOOD 2
#define SFX_LARGE_BLOOD 4
#define SFX_SMALL_SLIME 8
#define SFX_BIG_SLIME 16
#define SFX_ASH 32
#define SFX_BONES 64
#define SFX_RUBBLE 128
/* stuff done flags */
#define SDF_SPEC_LOC_X 301][0 // For special nodes to access the trigger location
#define SDF_SPEC_LOC_Y 301][1

View File

@@ -346,6 +346,9 @@ bool is_blocked(location to_check)
if (univ.town.is_force_barr(to_check.x,to_check.y))
return true;
if(univ.town.is_force_cage(to_check.x,to_check.y))
return true;
return false;
}
return true;

View File

@@ -724,6 +724,8 @@ bool try_move(short i,location start,short x,short y)
dest.x = dest.x + x;
dest.y = dest.y + y;
if((overall_mode == MODE_TOWN || overall_mode == MODE_COMBAT) && univ.town.is_force_cage(start.x,start.y))
return false;
if (overall_mode == MODE_TOWN)
return town_move_monster(i,dest);
@@ -909,6 +911,9 @@ void monst_inflict_fields(short which_monst)
damage_monst(which_monst,7,r1,0,DAMAGE_FIRE,0);
break;
}
if(univ.town.is_force_cage(where_check.x,where_check.y))
univ.town.monst[which_monst].status[eStatus::FORCECAGE] = 8;
else univ.town.monst[which_monst].status[eStatus::FORCECAGE] = 0;
}
if (univ.town.monst[which_monst].active > 0)
for (i = 0; i < univ.town.monst[which_monst].x_width; i++)
@@ -1011,7 +1016,7 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon
if (univ.town.is_fire_barr(where_check.x,where_check.y)) {
if ((which_m->attitude % 2 == 1) && (get_ran(1,1,100) < (which_m->mu * 10 + which_m->cl * 4))) {
play_sound(60);
add_string_to_buf("Monster breaks barrier.");
monst_spell_note(which_monst, 49);
univ.town.set_fire_barr(where_check.x,where_check.y,false);
}
else {
@@ -1025,11 +1030,12 @@ bool monst_check_special_terrain(location where_check,short mode,short which_mon
if ((which_m->attitude % 2 == 1) && (get_ran(1,1,100) < (which_m->mu * 10 + which_m->cl * 4))
&& (!univ.town->strong_barriers)) {
play_sound(60);
add_string_to_buf("Monster breaks barrier.");
monst_spell_note(which_monst, 49);
univ.town.set_force_barr(where_check.x,where_check.y,false);
}
else can_enter = false;
}
if(univ.town.is_force_cage(where_check.x,where_check.y)) can_enter = false;
if (univ.town.is_crate(where_check.x,where_check.y)) {
if (monster_placid(which_monst))
can_enter = false;
@@ -1364,7 +1370,7 @@ bool summon_monster(m_num_t which,location where,short duration,short given_atti
if (where.x == 0)
return false;
}
if ((univ.town.is_barrel(where.x,where.y)) || (univ.town.is_crate(where.x,where.y)))
if(univ.town.is_barrel(where.x,where.y) || univ.town.is_crate(where.x,where.y) || univ.town.is_block(where.x,where.y))
return false;
loc = where;
}

View File

@@ -1732,8 +1732,9 @@ void cast_town_spell(location where) ////
place_spell_pattern(current_pat,where,FIELD_DISPEL,7);
break;
case eSpell::MOVE_MOUNTAINS:
case eSpell::MOVE_MOUNTAINS_MASS:
add_string_to_buf(" You blast the area. ");
crumble_wall(where);
place_spell_pattern(current_pat, where, FIELD_SMASH, 7);
update_explored(univ.town.p_loc);
break;
case eSpell::BARRIER_FIRE:
@@ -1816,6 +1817,9 @@ void cast_town_spell(location where) ////
play_sound(41);
add_string_to_buf(" Didn't work. ");
}
} else if(univ.town.is_force_cage(where.x,where.y)) {
add_string_to_buf(" Cage broken.");
univ.town.set_force_cage(where.x,where.y,false);
}
else add_string_to_buf(" No barrier there.");
@@ -1950,6 +1954,9 @@ void dispel_fields(short i,short j,short mode)
r1 = get_ran(1,1,7) + mode;
if (r1 < 5)
univ.town.set_blade_wall(i,j,false);
r1 = get_ran(1,1,12) + mode;
if(r1 < 3)
univ.town.set_force_cage(i,j,false);
}
bool pc_can_cast_spell(short pc_num,eSkill type) {

View File

@@ -220,6 +220,10 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho
add_string_to_buf(" Magic barrier! ");
return false;
}
if(univ.town.is_force_cage(where_check.x,where_check.y)) {
add_string_to_buf(" Force cage!");
return false;
}
for (i = 0; i < 50; i++)
if (where_check == univ.town->special_locs[i]) {
if(univ.town->specials[univ.town->spec_id[i]].type == eSpecType::SECRET_PASSAGE) {
@@ -273,6 +277,10 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho
add_string_to_buf(" Magic barrier! ");
can_enter = false;
}
if (univ.town.is_force_cage(where_check.x,where_check.y)) {
add_string_to_buf(" Force cage! ");
can_enter = false;
}
if (univ.town.is_crate(where_check.x,where_check.y)) {
add_string_to_buf(" You push the crate.");
to_loc = push_loc(from_loc,where_check);
@@ -295,6 +303,13 @@ bool check_special_terrain(location where_check,eSpecCtx mode,short which_pc,sho
&& (univ.town.items[i].contained))
univ.town.items[i].item_loc = to_loc;
}
if(univ.town.is_block(where_check.x,where_check.y)) {
add_string_to_buf(" You push the stone block.");
to_loc = push_loc(from_loc,where_check);
univ.town.set_block(where_check.x,where_check.y,false);
if(to_loc.x > 0)
univ.town.set_block(to_loc.x,to_loc.y,false);
}
}
switch (ter_special) {
@@ -575,6 +590,11 @@ void check_fields(location where_check,eSpecCtx mode,short which_pc)
if (overall_mode < MODE_COMBAT)
boom_space(univ.party.p_loc,overall_mode,1,r1,12);
}
if(univ.town.is_force_cage(where_check.x,where_check.y)) {
if(univ.party[which_pc].status[eStatus::FORCECAGE] == 0)
add_string_to_buf(" Trapped in force cage!");
univ.party[which_pc].status[eStatus::FORCECAGE] = 8;
} else univ.party[which_pc].status[eStatus::FORCECAGE] = 0;
fast_bang = 0;
}
@@ -1776,7 +1796,7 @@ void push_things()////
}
if (univ.town.is_block(univ.town.p_loc.x,univ.town.p_loc.y)) {
ASB("You crash into the block.");
hit_party(get_ran(1, 1, 6), DAMAGE_UNBLOCKABLE);
hit_party(get_ran(1, 1, 6), DAMAGE_WEAPON);
}
for (k = 0; k < NUM_TOWN_ITEMS; k++)
if(univ.town.items[k].variety != eItemType::NO_ITEM && univ.town.items[k].contained
@@ -1814,7 +1834,7 @@ void push_things()////
}
if (univ.town.is_block(univ.town.p_loc.x,univ.town.p_loc.y)) {
ASB("You crash into the block.");
damage_pc(i,get_ran(1, 1, 6), DAMAGE_UNBLOCKABLE,eRace::UNKNOWN,0);
damage_pc(i,get_ran(1, 1, 6), DAMAGE_WEAPON,eRace::UNKNOWN,0);
}
for (k = 0; k < NUM_TOWN_ITEMS; k++)
if(univ.town.items[k].variety != eItemType::NO_ITEM && univ.town.items[k].contained
@@ -3035,6 +3055,7 @@ void ifthen_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
}
// TODO: Are there other object types to account for?
// TODO: Allow restricting to a specific rect
// TODO: Allow requiring a minimum and maximum number of objects
break;
case eSpecType::IF_PARTY_SIZE:
if (spec.ex2a < 1) {

View File

@@ -1191,6 +1191,12 @@ void monst_spell_note(m_num_t number,short which_mess)
case 48:
msg = " " + msg + " cleans off acid.";
break;
case 49:
msg = " " + msg + " breaks barrier.";
break;
case 50:
msg = " " + msg + " breaks force cage.";
break;
}
if (which_mess > 0)

View File

@@ -791,6 +791,7 @@ enum eEncNoteType {
NOTE_MONST,
};
// This is a slight misnomer, as a couple of these are not true fields.
enum eFieldType {
FIELD_NONE = 0,
FIELD_WEB = 1,
@@ -803,9 +804,22 @@ enum eFieldType {
WALL_ICE = 8,
WALL_BLADES = 9,
FIELD_QUICKFIRE = 10,
FIELD_DISPEL = 11,
FIELD_DISPEL = 11, // Dispel field
CLOUD_SLEEP = 12,
// TODO: Sfx fields, objects
OBJECT_CRATE = 13,
OBJECT_BARREL = 14,
BARRIER_CAGE = 15,
OBJECT_BLOCK = 16,
FIELD_SMASH = 17, // Move Mountains
SFX_SMALL_BLOOD = 18,
SFX_MEDIUM_BLOOD = 19,
SFX_LARGE_BLOOD = 20,
SFX_SMALL_SLIME = 21,
SFX_LARGE_SLIME = 22,
SFX_ASH = 23,
SFX_BONES = 24,
SFX_RUBBLE = 25,
SFX_SPECIAL = 26, // Special spot
};
enum class eSpell {