Beispiel #1
0
short sight_obscurity(short x,short y) {
	ter_num_t what_terrain;
	short store;
	
	what_terrain = coord_to_ter(x,y);
	
	// TODO: This should not be hard-coded!
	// It appears to refer to mountain cave entrances, surface tower, and surface pit. (WHY?)
	if((what_terrain >= 237) && (what_terrain <= 242))
		return 1;
	
	store = get_blockage(what_terrain);
	
	if(is_town()) {
		if(univ.town.is_special(x,y))
			store++;
	}
	
	if((is_town()) || (is_combat())) {
		if(univ.town.is_web(x,y))
			store += 2;
		if((univ.town.is_fire_barr(x,y)) || (univ.town.is_force_barr(x,y)))
			return 5;
		if(univ.town.is_crate(x,y) || univ.town.is_barrel(x,y) || univ.town.is_block(x,y))
			store++;
		
	}
	return store;
}
Beispiel #2
0
// All purpose function to check is spot is free for travel into.
bool is_blocked(location to_check) {
	short i,gr;
	ter_num_t ter;
	
	if(is_out()) {
		if(impassable(univ.out[to_check.x][to_check.y])) {
			return true;
		}
		if(to_check == univ.party.p_loc)
			return true;
		for(i = 0; i < univ.party.out_c.size(); i++)
			if((univ.party.out_c[i].exists))
				if(univ.party.out_c[i].m_loc == to_check)
					return true;
		return false;
	}
	
	if((is_town()) || (is_combat())) {
		ter = univ.town->terrain(to_check.x,to_check.y);
		gr = univ.scenario.ter_types[ter].picture;
		
		// Terrain blocking?
		if(impassable(ter)) {
			return true;
		}
		
		// Keep away from marked specials during combat
		if((is_combat()) && univ.town.is_spot(to_check.x, to_check.y))
			return true;
		if((is_combat()) && (univ.scenario.ter_types[coord_to_ter(to_check.x,to_check.y)].trim_type == eTrimType::CITY))
			return true; // TODO: Maybe replace eTrimType::CITY with a blockage == clear/special && is_special() check
		// Note: The purpose of the above check is to avoid portals.
		
		// Party there?
		if(is_town())
			if(to_check == univ.town.p_loc)
				return true;
		if(is_combat())
			for(i = 0; i < 6; i++)
				if(univ.party[i].main_status == eMainStatus::ALIVE && to_check == univ.party[i].combat_pos)
					return true;
		
		// Monster there?
		if(univ.target_there(to_check, TARG_MONST))
			return true;
		
		// Magic barrier?
		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;
}
Beispiel #3
0
bool is_town() {
	if((overall_mode > MODE_OUTDOORS && overall_mode < MODE_COMBAT) || overall_mode == MODE_LOOK_TOWN || cartoon_happening)
		return true;
	else if(overall_mode == MODE_SHOPPING) {
		std::swap(overall_mode, store_pre_shop_mode);
		bool ret = is_town();
		std::swap(overall_mode, store_pre_shop_mode);
		return ret;
	} else if(overall_mode == MODE_TALKING) {
		std::swap(overall_mode, store_pre_talk_mode);
		bool ret = is_town();
		std::swap(overall_mode, store_pre_talk_mode);
		return ret;
	} else return false;
}
Beispiel #4
0
// Looks at all spaces within 2, looking for a spot which is clear of nastiness and beings
// returns {0,0} if none found
// THIS MAKES NO ADJUSTMENTS FOR BIG MONSTERS!!!
location find_clear_spot(location from_where,short mode)
//mode; // 0 - normal  1 - prefer adjacent space
{
	location loc,store_loc;
	short num_tries = 0,r1;
	
	while (num_tries < 75) {
		num_tries++;
		loc = from_where;
		r1 = get_ran(1,-2,2);
		loc.x = loc.x + r1;
		r1 = get_ran(1,-2,2);
		loc.y = loc.y + r1;
		if ((loc_off_act_area(loc) == false) && (is_blocked(loc) == false)
			&& (can_see(from_where,loc,1) == 0)
			&& (!(is_combat()) || (pc_there(loc) == 6))
			&& (!(is_town()) || (loc != univ.town.p_loc))
			 && (!(univ.town.misc_i(loc.x,loc.y) & 248)) && // check for crate, barrel, barrier, quickfire
			(!(univ.town.explored(loc.x,loc.y) & 254))) { // check for fields, clouds
				if ((mode == 0) || ((mode == 1) && (adjacent(from_where,loc) == true)))
					return loc;
					else store_loc = loc;			
				}
		}
	return store_loc;
}
Beispiel #5
0
short monst_pick_target_pc(short m_num,cCreature *which_m)////
{
	short num_tries = 0,r1,store_targ = 6;

	if (which_m->attitude % 2 == 0)
		return 6;
	if (is_town())
		return 0;
	
	// First pick any visible, nearby PC
	r1 = get_ran(1,0,5);
	while ((num_tries < 6) && ((univ.party[r1].main_status != 1) ||
		(monst_can_see(m_num,pc_pos[r1]) == false))) {
			r1 = get_ran(1,0,5);
			num_tries++;
			}
	if (num_tries < 6)
		store_targ = r1;
	
	// Then, see if target can be replaced with someone nice and close
	r1 = get_ran(1,0,5);
	while ((num_tries < 6) && ((univ.party[r1].main_status != 1) ||
		(dist(which_m->cur_loc,pc_pos[r1]) > 4) ||
		(monst_can_see(m_num,pc_pos[r1]) == false))) {
			r1 = get_ran(1,0,5);
			num_tries++;
			}

	if (num_tries < 6)
		return r1;
		else return store_targ;
}
Beispiel #6
0
// Returns 6 if can't see, O.W. returns the # of a PC that can see
short party_can_see(location where) {
	short i;
	
	if(is_out()) {
		if((point_onscreen(univ.party.p_loc,where)) && (can_see_light(univ.party.p_loc,where,sight_obscurity) < 5))
			return 1;
		else return 6;
	}
	if(fog_lifted)
		return point_onscreen(univ.town.p_loc,where) ? 1 : 6;
	if(is_town()) {
		if( ((point_onscreen(univ.town.p_loc,where)) || (overall_mode == MODE_LOOK_TOWN)) && (pt_in_light(univ.town.p_loc,where) )
			&& (can_see_light(univ.town.p_loc,where,sight_obscurity) < 5))
			return 1;
		else return 6;
	}
	
	// Now for combat checks. Doing separately for efficiency. Check first for light. If
	//   dark, give up.
	if((which_combat_type != 0) && !combat_pt_in_light(where))
		return 6;
	
	for(i = 0; i < 6; i++)
		if(univ.party[i].main_status == eMainStatus::ALIVE) {
			if(can_see_light(univ.party[i].combat_pos,where,sight_obscurity) < 5)
				return i;
		}
	
	return 6;
}
Beispiel #7
0
//short dest; // 0 - terrain gworld   1 - screen
// if terrain_to_draw is -1, do black
// if terrain_to_draw >= 10000, force to draw graphic which is terrain_to_draw - 10000
void draw_one_terrain_spot (short i,short j,short terrain_to_draw) {
	rectangle where_draw;
	rectangle source_rect;
	sf::Texture* source_gworld;
	short anim_type = 0;
	location l;
	
	l.x = i; l.y = j;
	if(supressing_some_spaces && (l != ok_space[0]) && (l != ok_space[1]) && (l != ok_space[2]) && (l != ok_space[3]))
		return;
	
	where_draw = calc_rect(i,j);
 	where_draw.offset(13,13);
 	if(terrain_to_draw == -1) {
		fill_rect(terrain_screen_gworld, where_draw, sf::Color::Black);
		return;
	}
 	
	if(terrain_to_draw >= 10000) { // force using a specific graphic
		terrain_to_draw -= 10000;
		int which_sheet = terrain_to_draw / 50;
		source_gworld = ResMgr::get<ImageRsrc>("ter" + std::to_string(1 + which_sheet)).get();
		terrain_to_draw %= 50;
		source_rect = calc_rect(terrain_to_draw % 10, terrain_to_draw / 10);
		anim_type = -1;
	}
	else if(univ.scenario.ter_types[terrain_to_draw].picture >= 2000) { // custom
		graf_pos_ref(source_gworld, source_rect) = spec_scen_g.find_graphic(univ.scenario.ter_types[terrain_to_draw].picture - 2000 + (anim_ticks % 4));
		anim_type = 0;
	}
	else if(univ.scenario.ter_types[terrain_to_draw].picture >= 1000) { // custom
		graf_pos_ref(source_gworld, source_rect) = spec_scen_g.find_graphic(univ.scenario.ter_types[terrain_to_draw].picture - 1000);
	}
	else if(univ.scenario.ter_types[terrain_to_draw].picture >= 960) { // animated
		source_gworld = ResMgr::get<ImageRsrc>("teranim").get();
		terrain_to_draw = univ.scenario.ter_types[terrain_to_draw].picture;
		source_rect = calc_rect(4 * ((terrain_to_draw - 960) / 5) + (anim_ticks % 4),(terrain_to_draw - 960) % 5);
		anim_type = 0;
	}
	else {
		terrain_to_draw = univ.scenario.ter_types[terrain_to_draw].picture;
		int which_sheet = terrain_to_draw / 50;
		source_gworld = ResMgr::get<ImageRsrc>("ter" + std::to_string(1 + which_sheet)).get();
		terrain_to_draw %= 50;
		source_rect = calc_rect(terrain_to_draw % 10, terrain_to_draw / 10);
		anim_type = -1;
	}
	
	if(anim_type >= 0) {
		if((is_town()) || (is_out()))
			anim_onscreen = true;
	}
	
	rect_draw_some_item(*source_gworld, source_rect, terrain_screen_gworld, where_draw);
}
Beispiel #8
0
// returns true if placement was successful
bool summon_monster(m_num_t which,location where,short duration,short given_attitude)
//which; // if in town, this is caster loc., if in combat, this is where to try
					// to put monster
{
	location loc;
	short which_m,spot;

	if ((is_town()) || (monsters_going)) {
		// Ooooh ... mondo kludge. Need to find caster's attitude to give it to monst.
		which_m = monst_there(where);
//		if (pc_there(where) < 6) 
//			which_att = 2;
//			else if (which_m == 90)
//				which_att = 1;
//				else which_att = univ.town.monst[which_m].attitude;
		loc = find_clear_spot(where,0);
		if (loc.x == 0)
			return false;
		}
		else {
			// pc may be summoning using item, in which case where will be pc's space, so fix
			if (pc_there(where) < 6) {
				where = find_clear_spot(where,0);
				if (where.x == 0)
					return false;
				}
			if ((univ.town.is_barrel(where.x,where.y)) || (univ.town.is_crate(where.x,where.y)))
				return false;
			loc = where;
			}
			
	spot = place_monster(which,loc);
	if (spot >= univ.town->max_monst()) {
		if (duration < 100)
			add_string_to_buf("  Too many monsters.");
			//ASB("  Monster fails to summon monster.");
		return false;
		}
	//play_sound(61);
		
//	if (duration < 100)
		univ.town.monst[spot].attitude = given_attitude;
//		else univ.town.monst[spot].attitude = which_att;
	
	if (which > 0) {//monster here for good
		univ.town.monst[spot].summoned = duration;
		monst_spell_note(which,21);
		}
		else univ.town.monst[spot].summoned = 0;
		
	return true;
}
Beispiel #9
0
void handle_menu_choice(eMenu item_hit) {
	std::string dialogToShow;
	sf::Event dummyEvent = {sf::Event::KeyPressed};
	short i, choice;
	
	switch(item_hit) {
		case eMenu::NONE: break;
		case eMenu::FILE_OPEN:
			do_load();
			break;
		case eMenu::FILE_SAVE:
			do_save(0);
			break;
		case eMenu::FILE_SAVE_AS:
			do_save(1);
			break;
		case eMenu::FILE_NEW:
			if(overall_mode != MODE_STARTUP) {
				std::string choice = cChoiceDlog("restart-game",{"okay","cancel"}).show();
				if(choice == "cancel")
					return;
				for(i = 0; i < 6; i++)
					univ.party[i].main_status = eMainStatus::ABSENT;
				party_in_memory = false;
				reload_startup();
				overall_mode = MODE_STARTUP;
				draw_startup(0);
			}
			start_new_game();
			draw_startup(0);
			menu_activate();
			break;
		case eMenu::FILE_ABORT:
			if(overall_mode != MODE_STARTUP) {
				std::string choice = cChoiceDlog("abort-game",{"okay","cancel"}).show();
				if (choice=="cancel") return;
				reload_startup();
				overall_mode = MODE_STARTUP;
			}
			party_in_memory = false;
			draw_startup(0);
			menu_activate();
			break;
		case eMenu::PREFS:
			pick_preferences();
			break;
		case eMenu::QUIT:
			if(overall_mode == MODE_STARTUP) {
				if(party_in_memory) {
					std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show();
					if(choice == "cancel") break;
					if(choice == "save") {
						fs::path file = nav_put_party();
						if(!file.empty()) break;
						save_party(file, univ);
					}
				}
				All_Done = true;
				break;
			}
			if(overall_mode > MODE_TOWN) {
				std::string choice = cChoiceDlog("quit-confirm-nosave",{"quit","cancel"}).show();
				if(choice == "cancel")
					return;
			}
			else {
				std::string choice = cChoiceDlog("quit-confirm-save",{"quit","save","cancel"}).show();
				if(choice == "cancel")
					break;
				if(choice == "save") {
					if(univ.file.empty()) {
						univ.file = nav_put_party();
						if(univ.file.empty()) break;
					}
					save_party(univ.file, univ);
				}
			}
			All_Done = true;
			break;
		case eMenu::OPTIONS_PC_GRAPHIC:
			choice = char_select_pc(1,"New graphic for who?");
			if(choice < 6)
				pick_pc_graphic(choice,1,nullptr);
			draw_terrain();
			break;
			
		case eMenu::OPTIONS_DELETE_PC:
			if(!prime_time()) {
				ASB("Finish what you're doing first.");
				print_buf();
			}
			else {
				choice = char_select_pc(1,"Delete who?");
				if(choice < 6) {
					std::string confirm = cChoiceDlog("delete-pc-confirm",{"yes","no"}).show();
					if(confirm == "yes")
						kill_pc(univ.party[choice],eMainStatus::ABSENT);
				}
				draw_terrain();
			}
			break;
			
			
		case eMenu::OPTIONS_RENAME_PC:
			choice = char_select_pc(1,"Rename who?");
			if(choice < 6)
				pick_pc_name(choice,nullptr);
			put_pc_screen();
			put_item_screen(stat_window);
			break;
			
			
		case eMenu::OPTIONS_NEW_PC:
			if(!(is_town())) {
				add_string_to_buf("Add PC: Town mode only.");
				print_buf();
				break;
			}
			for(i = 0; i < 6; i++)
				if(univ.party[i].main_status == eMainStatus::ABSENT)
					i = 20;
			if(i == 6) {
				ASB("Add PC: You already have 6 PCs.");
				print_buf();
				break;
			}
			if(univ.town->has_tavern) {
				give_help(56,0);
				create_pc(6,nullptr);
			} else {
				add_string_to_buf("Add PC: You cannot add new characters in this town. Try in the town you started in.", 2);
			}
			print_buf();
			put_pc_screen();
			put_item_screen(stat_window);
			break;
			
		case eMenu::OPTIONS_JOURNAL:
			journal();
			break;
		case eMenu::OPTIONS_TALK_NOTES:
			if(overall_mode == MODE_TALKING) {
				ASB("Talking notes: Can't read while talking.");
				print_buf();
				return;
			}
			talk_notes();
			break;
		case eMenu::OPTIONS_ENCOUNTER_NOTES:
			adventure_notes();
			break;
		case eMenu::OPTIONS_STATS:
			if(overall_mode != MODE_STARTUP)
				print_party_stats();
			break;
		case eMenu::HELP_OUT:
			dialogToShow = "help-outdoor";
			break;
		case eMenu::HELP_TOWN:
			dialogToShow = "help-town";
			break;
		case eMenu::HELP_COMBAT:
			dialogToShow = "help-combat";
			break;
		case eMenu::HELP_BARRIER:
			dialogToShow = "help-fields";
			break;
		case eMenu::HELP_HINTS:
			dialogToShow = "help-hints";
			break;
		case eMenu::HELP_SPELLS:
			dialogToShow = "help-magic";
			break;
		case eMenu::ABOUT:
			dialogToShow = "about-boe";
			break;
		case eMenu::LIBRARY_MAGE:
			display_spells(eSkill::MAGE_SPELLS,100,0);
			break;
		case eMenu::LIBRARY_PRIEST:
			display_spells(eSkill::PRIEST_SPELLS,100,0);
			break;
		case eMenu::LIBRARY_SKILLS:
			display_skills(eSkill::INVALID,0);
			break;
		case eMenu::LIBRARY_ALCHEMY:
			// TODO: Create a dedicated dialog for alchemy info
			display_alchemy();
			break;
		case eMenu::LIBRARY_TIPS:
			tip_of_day();
			break;
		case eMenu::LIBRARY_INTRO:
			dialogToShow = "welcome";
			break;
		case eMenu::ACTIONS_ALCHEMY:
			dummyEvent.key.code = sf::Keyboard::A;
			dummyEvent.key.shift = true;
			handle_keystroke(dummyEvent);
			break;
		case eMenu::ACTIONS_WAIT:
			dummyEvent.key.code = sf::Keyboard::W;
			handle_keystroke(dummyEvent);
			break;
		case eMenu::ACTIONS_AUTOMAP:
			if(!prime_time()) {
				ASB("Finish what you're doing first.");
				print_buf();
			}
			else {
				give_help(62,0);
				display_map();
			}
			make_cursor_sword();
			break;
		case eMenu::HELP_TOC:
			if(fs::is_directory(progDir/"doc"))
				launchURL("file://" + (progDir/"doc/game/Contents.html").string());
			else launchURL("https://blades.calref.net/doc/game/Contents.html");
			break;
		case eMenu::ABOUT_MAGE:
		case eMenu::ABOUT_PRIEST:
			give_help(209,0);
			break;
		case eMenu::ABOUT_MONSTERS:
			give_help(212,0);
			break;
	}
	if(!dialogToShow.empty()) {
		cChoiceDlog dlog(dialogToShow);
		dlog.show();
	}
}
Beispiel #10
0
Boolean handle_menu (short item, HMENU)
{
    short choice,i;
    POINT x = {1001,0},pass_point;
    Boolean to_return = false;

    switch (item) {
    case 1:  // File Menu
        if (in_startup_mode == true) startup_load();
        else do_load();
        break;
    case 2:
        do_save(0);
        break;
    case 3:
        if (in_startup_mode == true) save_file(1);
        else do_save(1);
        break;
    case 4:
        if (in_startup_mode == false)
        {
            choice = FCD(1091,0);
            if (choice == 1) return false;
            for (i = 0; i < 6; i++)
                adven[i].main_status = MAIN_STATUS_ABSENT;
            party_in_memory = false;
            reload_startup();
            in_startup_mode = true;
            draw_startup(0);
        }
        start_new_game();
        draw_startup(0);
        break;
    case 6:
        pick_preferences();
        break;
    case 7:
        pick_compatibility();
        break;
    case 8:  // Quit
        if (in_startup_mode == true) {
            to_return = All_Done = true;
            break;
        }
        if (overall_mode > MODE_TOWN) {
            choice = FCD(1067,0);
            if (choice == 1) return All_Done;
        }
        else {
            choice = FCD(1066,0);
            if (choice == 3)
                break;
            if (choice == 1)
                save_file(0);
        }
        to_return = All_Done = true;
        break;

    // Options menu
    case 21:
        choice = char_select_pc(0,0,"New graphic for who?");
        if (choice < 6)
            pick_pc_graphic(choice,1,0);
        initiate_redraw();
        break;

    case 22:
        choice = select_pc(0,0);
        if (choice < 6)
            pick_pc_name(choice,0);
        put_pc_screen();
        put_item_screen(stat_window,0);
        break;


    case 23:
        if (!(is_town())) {
            add_string_to_buf("Add PC: Town mode only.");
            print_buf();
            break;
        }
        for (i = 0; i < NUM_OF_PCS; i++)
            if (adven[i].main_status == MAIN_STATUS_ABSENT)
                i = 20;
        if (i == INVALID_PC) {
            ASB("Add PC: You already have 6 PCs.");
            print_buf();
        }
        if (c_town.town_num == scenario.which_town_start) {
            give_help(56,0,0);
            create_pc(6,0);
        }
        else {
            add_string_to_buf("Add PC: You can only make new");
            add_string_to_buf("  characters in the town you ");
            add_string_to_buf("  started in.");
        }
        print_buf();
        put_pc_screen();
        put_item_screen(stat_window,0);
        break;

    case 24:
        if (prime_time() == false) {
            ASB("Finish what you're doing first.");
            print_buf();
        }
        else {
            choice = char_select_pc(0,0,"Delete who?");
            if (choice < 6) {
                if ((i = FCD(1053,0)) == 2)
                    adven[choice].kill(0);
            }
            initiate_redraw();
        }
        break;

    case 27:
        if (overall_mode == MODE_TALKING) {
            ASB("Talking notes: Can't read while talking.");
            print_buf();
            return to_return;
        }
        talk_notes();
        break;
    case 28:
        adventure_notes();
        break;
    case 29:
        if (in_startup_mode == false) print_party_stats();
        break;

    // Help menu
    case 41:
        FCD(1079,0);
        break;
    case 42:
        FCD(1080,0);
        break;
    case 43:
        FCD(1081,0);
        break;
    case 44:
        FCD(1072,0);
        break; // magic barriers
    case 46:
        FCD(1084,0);
        break;
    case 47:
        FCD(1088,0);
        break;

    // Library
    case 61:
        display_spells(0,100,0);
        break;
    case 62:
        display_spells(1,100,0);
        break;
    case 63:
        display_skills(100,0);
        break;
    case 64:
        display_help(0,0);
        break;
    case 65:
        tip_of_day();
        break;
    case 67:
        FCD(986,0);
        break;

    // Actions
    case 81:
        if (overall_mode != MODE_TOWN) {
            ASB("Alchemy: In town mode only.");
            print_buf();
            break;
        }
        pass_point.x = 1000;
        pass_point.y = 405;
        to_return = handle_action(pass_point,(WPARAM) 0,(LPARAM)-1);
        break;
    case 82:
        to_return = handle_action(x,(WPARAM) 0,(LPARAM)-1);
        break;
    case 84:
        if (prime_time() == false) {
            ASB("Finish what you're doing first.");
            print_buf();
        }
        else {
            give_help(62,0,0);
            display_map();
        }
        SetCursor(sword_curs);
        break;

    // Mage is 399
    case 399:
        give_help(209,0,0);
        party.help_received[9] = false;
        break;

    // Priest is 499
    case 499:
        give_help(209,0,0);
        party.help_received[9] = false;
        break;

    // Monsters is 599
    case 599:
        give_help(212,0,0);
        break;

    case 100: // Index
        WinHelp(mainPtr,"Blades of Exile.hlp",HELP_CONTENTS,0L);
        break;

    case 200: // About
        FCD(1062,0);
        break;

    default:
        if ((item >= 400) && (item < 500))  { // mage spell
            if (prime_time() == false) {
                ASB("Finish what you're doing first.");
                print_buf();
            }
            else handle_menu_spell(item - 400,0);
            break;
        }
        if ((item >= 500) && (item < 600))  { // priest spell
            if (prime_time() == false) {
                ASB("Finish what you're doing first.");
                print_buf();
            }
            else handle_menu_spell(item - 500,1);
            break;
        }
        if ((item >= 600) && (item < 700))  { // monster spell
            display_monst(item - 600,(creature_data_type *) NULL,1);
            break;
        }
        break;
    }
    if (in_startup_mode == true)
        menu_activate(0);
    else menu_activate(1);
    return to_return;
}
Beispiel #11
0
bool monst_check_special_terrain(location where_check,short mode,short which_monst)
//mode; // 1 - town 2 - combat
{
	ter_num_t ter = 0;
	short r1,i,guts = 0;
	bool can_enter = true,mage = false;
	location from_loc,to_loc;
	bool do_look = false; // If becomes true, terrain changed, so need to update what party sees
	cCreature *which_m;
	short ter_abil;
	unsigned short ter_flag;
	
	from_loc = univ.town.monst[which_monst].cur_loc;
	switch (mode) {	
		case 1:
			ter = univ.town->terrain(where_check.x,where_check.y);
			break;	
		case 2:
			ter = combat_terrain[where_check.x][where_check.y];
			break;	
		}
	////
	which_m = &univ.town.monst[which_monst];
	ter_abil = scenario.ter_types[ter].special;
	ter_flag = scenario.ter_types[ter].flag3.u;
	
		if ((mode > 0) && (ter_abil == TER_SPEC_CONVEYOR)) {
			if (
				((ter_flag == DIR_N) && (where_check.y > from_loc.y)) ||
				((ter_flag == DIR_E) && (where_check.x < from_loc.x)) ||
				((ter_flag == DIR_S) && (where_check.y < from_loc.y)) ||
				((ter_flag == DIR_W) && (where_check.x > from_loc.x)) ) {
					return false;
					}
			}

	// begin determining guts, which determines how enthused the monst is about entering
	// nasty barriers
	if ((which_m->mu > 0) || (which_m->cl > 0))
		mage = true;
	if (which_m->spec_skill == 13)
		guts = 20;
		else guts = get_ran(1,1,(which_m->level / 2));
	guts += which_m->health / 20;
	if (mage == true)
		guts = guts / 2;
	if (which_m->attitude == 0)
		guts = guts / 2;
		
	if ((univ.town.is_antimagic(where_check.x,where_check.y)) && (mage == true))
		return false;
	if ((univ.town.is_fire_wall(where_check.x,where_check.y)) && (which_m->spec_skill != 22)) {
			if (guts < 3) return false;
		}
	if (univ.town.is_force_wall(where_check.x,where_check.y)) {
			if (guts < 4) return false;
		}
	if ((univ.town.is_ice_wall(where_check.x,where_check.y)) && (which_m->spec_skill != 23)) {
			if (guts < 5) return false;
		}
	if (univ.town.is_sleep_cloud(where_check.x,where_check.y)) {
			if (guts < 8) return false;
		}
	if (univ.town.is_blade_wall(where_check.x,where_check.y)) {
			if (guts < 8) return false;
		}
	if (univ.town.is_quickfire(where_check.x,where_check.y)) {
			if (guts < 8) return false;
		}
	if (univ.town.is_scloud(where_check.x,where_check.y)) {
		if (guts < 4) return false;
		}
	if ((univ.town.is_web(where_check.x,where_check.y)) && (which_m->m_type != 12)) {
		if (guts < 3) return false;
		}
	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.");
			univ.town.set_fire_barr(where_check.x,where_check.y,false);
			}
			else {
				if (guts < 6) return false;
				r1 = get_ran(1,0,10);
				if ((r1 < 8) || (monster_placid(which_monst)))
					can_enter = false;
				}
		}
	if (univ.town.is_force_barr(where_check.x,where_check.y)) { /// Not in big towns
		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.");
			univ.town.set_force_barr(where_check.x,where_check.y,false);
			}
			else can_enter = false;
		}
	if (univ.town.is_crate(where_check.x,where_check.y)) {
		if (monster_placid(which_monst))
			can_enter = false;
			else {
				to_loc = push_loc(from_loc,where_check);
				univ.town.set_crate((short) where_check.x,(short) where_check.y,false);
				if (to_loc.x > 0)
					univ.town.set_crate((short) to_loc.x,(short) to_loc.y, true);
				for (i = 0; i < NUM_TOWN_ITEMS; i++)
					if ((univ.town.items[i].variety > 0) && (univ.town.items[i].item_loc == where_check)
					 && (univ.town.items[i].contained))
			 			univ.town.items[i].item_loc = to_loc;
						}
		}
	if (univ.town.is_barrel(where_check.x,where_check.y)) {
		if (monster_placid(which_monst))
			can_enter = false;
			else {
				to_loc = push_loc(from_loc,where_check);
				univ.town.set_barrel((short) where_check.x,(short) where_check.y,false);
				if (to_loc.x > 0)
				    	univ.town.set_barrel((short) to_loc.x,(short) to_loc.y,true);
				for (i = 0; i < NUM_TOWN_ITEMS; i++)
					if ((univ.town.items[i].variety > 0) && (univ.town.items[i].item_loc == where_check)
					 && (univ.town.items[i].contained))
			 			univ.town.items[i].item_loc = to_loc;
				
				}
		}
	if (monster_placid(which_monst) && // monsters don't hop into bed when things are calm
		(scenario.ter_types[ter].special == TER_SPEC_BED))
				can_enter = false;
	if (mode == 1 && univ.town.is_spot(where_check.x, where_check.y))
		can_enter = false;
	if (ter == 90) {
			if ((is_combat()) && (which_combat_type == 0)) {
				univ.town.monst[which_monst].active = 0;
				add_string_to_buf("Monster escaped! ");
				}
			return false;
		}
				
	switch (ter_abil) {
		// changing ter
		case TER_SPEC_CHANGE_WHEN_STEP_ON:
			can_enter = false;
			if (!(monster_placid(which_monst))) {
				univ.town->terrain(where_check.x,where_check.y) = scenario.ter_types[ter].flag1.u;
				combat_terrain[where_check.x][where_check.y] = scenario.ter_types[ter].flag1.u;
				do_look = true;
				if (point_onscreen(center,where_check))
					play_sound(scenario.ter_types[ter].flag2.u);
				}
			break;

		case TER_SPEC_BLOCKED_TO_MONSTERS:
		case TER_SPEC_TOWN_ENTRANCE:
		case TER_SPEC_WATERFALL: 
			can_enter = false;
			break;
						
		case TER_SPEC_DAMAGING: // TODO: Update this to check other cases
			if (ter_flag == DAMAGE_FIRE && univ.town.monst[which_monst].immunities & 8)
				return true;
				else return false;
			break;
		}

	// Action may change terrain, so update what's been seen
	if (do_look == true) {
		if (is_town())
			update_explored(univ.town.p_loc);
		if (is_combat())
			for (i = 0; i < 6; i++)
				if (univ.party[i].main_status == 1)
					update_explored(pc_pos[i]);
		}
		
	return can_enter;
}
Beispiel #12
0
short switch_target_to_adjacent(short which_m,short orig_target)
{
	location monst_loc;
	short i,num_adj = 0;
	
	monst_loc = univ.town.monst[which_m].cur_loc;

	// First, take care of friendly monsters.
	if (univ.town.monst[which_m].attitude % 2 == 0) {
		if (orig_target >= 100)
			if ((univ.town.monst[orig_target - 100].active > 0) &&
			 (monst_adjacent(univ.town.monst[orig_target - 100].cur_loc,which_m) == true))
				return orig_target;
		for (i = 0; i < univ.town->max_monst(); i++)
			if ((univ.town.monst[i].active > 0) &&
			 (univ.town.monst[i].attitude % 2 == 1) &&
			 (monst_adjacent(univ.town.monst[i].cur_loc,which_m) == true))
				return i + 100;
		return orig_target;
		}

	// If we get here while in town, just need to check if switch to pc
	if ((is_town()) && (monst_adjacent(univ.town.p_loc,which_m) == true))
		return 0;
	if (is_town())
		return orig_target;
		
	// If target is already adjacent, we're done here.
	if ((is_combat()) && (orig_target < 6))
		if ((univ.party[orig_target].main_status == 1) && (monst_adjacent(pc_pos[orig_target],which_m) == true))
			return orig_target;
	if (orig_target >= 100)
		if ((univ.town.monst[orig_target - 100].active > 0) &&
		 (monst_adjacent(univ.town.monst[orig_target - 100].cur_loc,which_m) == true))
			return orig_target;
	
	// Anyone unarmored? Heh heh heh...
	if (is_combat())
		for (i = 0; i < 6; i++)
			if ((univ.party[i].main_status == 1) && (monst_adjacent(pc_pos[i],which_m) == true) && 
			 (get_encumberance(i) < 2))
		 		return i; 

	// Check for a nice, adjacent, friendly monster and maybe attack
	for (i = 0; i < univ.town->max_monst(); i++)
		if ((univ.town.monst[i].active > 0) &&
		 (univ.town.monst[i].attitude % 2 == 0) &&
		 (monst_adjacent(univ.town.monst[i].cur_loc,which_m) == true) &&
		 (get_ran(1,0,2) < 2))
			return i + 100;

	// OK. Now if this monster has PCs adjacent, pick one at randomn and hack. Otherwise,
	// stick with orig. target.
	for (i = 0; i < 6; i++)
		if ((univ.party[i].main_status == 1) && (monst_adjacent(pc_pos[i],which_m) == true)) 
			num_adj++;

	if (num_adj == 0)	
		return orig_target;
	
	i = 0;
	num_adj = get_ran(1,1,num_adj);
	while ((num_adj > 1) || (univ.party[i].main_status != 1) || (monst_adjacent(pc_pos[i],which_m) == false)) {
		if ((univ.party[i].main_status == 1) && (monst_adjacent(pc_pos[i],which_m) == true)) 
			num_adj--;
		i++;
		}
	return i;
}
Beispiel #13
0
short monst_pick_target(short which_m)
{
	cCreature *cur_monst;
	short targ_pc,targ_m;

	cur_monst = &univ.town.monst[which_m];

	// First, any chance target is screwed?
	if (univ.town.monst[which_m].target >= 100) {
	if (((cur_monst->attitude % 2 == 1) && 
		(univ.town.monst[univ.town.monst[which_m].target - 100].attitude == cur_monst->attitude)) ||
		((cur_monst->attitude % 2 == 0) && (univ.town.monst[univ.town.monst[which_m].target - 100].attitude % 2 == 0)))
			univ.town.monst[which_m].target = 6;
			else if (univ.town.monst[univ.town.monst[which_m].target - 100].active == 0)
				univ.town.monst[which_m].target = 6;
			}
	if (univ.town.monst[which_m].target < 6) 
		if ((univ.party[univ.town.monst[which_m].target].main_status != 1) || (get_ran(1,0,3) == 1))
			univ.town.monst[which_m].target = 6;		
	
	if ((is_combat()) && (cur_monst->attitude % 2 == 1)) {
		if (spell_caster < 6)
			if ((get_ran(1,1,5) < 5) && (monst_can_see(which_m,pc_pos[spell_caster]) == true)
					&& (univ.party[spell_caster].main_status == 1)) 
						return spell_caster;
		if (missile_firer < 6)
			if ((get_ran(1,1,5) < 3) && (monst_can_see(which_m,pc_pos[missile_firer]) == true)
				&& (univ.party[missile_firer].main_status == 1)) 
					return missile_firer;
		if (univ.town.monst[which_m].target < 6)
			if ((monst_can_see(which_m,pc_pos[univ.town.monst[which_m].target]) == true)
				&& (univ.party[univ.town.monst[which_m].target].main_status == 1)) 
					return univ.town.monst[which_m].target;
		}

//	if (monst_target[which_m] >= 100) {
//		if ((can_see(cur_monst->m_loc,univ.town.monst[monst_target[which_m] - 100].m_loc,0) < 4)
//			&& (univ.town.monst[monst_target[which_m] - 100].active > 0)) 
//				return monst_target[which_m];
//		}
		
	// Now pick a target pc and a target monst and see which is more attractive
	targ_pc = monst_pick_target_pc(which_m,cur_monst);
	targ_m = monst_pick_target_monst(cur_monst);
	
	if ((targ_pc != 6) && (targ_m == 6))
		return targ_pc;
	if ((targ_pc == 6) && (targ_m != 6))
		return targ_m;
	if ((targ_pc == 6) && (targ_m == 6))
		return 6;
		
	if (is_town()) {
		if (cur_monst->attitude % 2 == 0) {
			return targ_m;
			}
		if ((targ_m == 6) && (cur_monst->attitude % 2 == 1))
			return 0;
		if (dist(cur_monst->cur_loc,univ.town.monst[targ_m - 100].cur_loc) <
			dist(cur_monst->cur_loc,univ.town.p_loc))
				return targ_m;
				else return 0;
		}
	// Otherwise we're in combat
	if ((dist(cur_monst->cur_loc,univ.town.monst[targ_m - 100].cur_loc) ==
		dist(cur_monst->cur_loc,pc_pos[targ_pc])) && (get_ran(1,0,6) < 3))
			return targ_m;
			else return targ_pc;
	if (dist(cur_monst->cur_loc,univ.town.monst[targ_m - 100].cur_loc) <
		dist(cur_monst->cur_loc,pc_pos[targ_pc]))
			return targ_m;
			else return targ_pc;

}
Beispiel #14
0
void draw_party_symbol(location center) {
	rectangle source_rect;
	location target(4,4);
	short i = 0;
	
	if(!can_draw_pcs)
		return;
	if(!univ.party.is_alive())
		return;
	if((is_town()) && (univ.town.p_loc.x > 70))
		return;
	if(overall_mode == MODE_LOOK_TOWN || cartoon_happening) {
		target.x += univ.town.p_loc.x - center.x;
		target.y += univ.town.p_loc.y - center.y;
	}
	
	if((univ.party.in_boat < 0) && (univ.party.in_horse < 0)) {
		i = first_active_pc();
		sf::Texture* from_gw;
		pic_num_t pic = univ.party[i].which_graphic;
		if(pic >= 1000) {
			bool isParty = pic >= 10000;
			pic_num_t need_pic = pic % 1000;
			if(univ.party.direction >= 4)
				need_pic++;
			graf_pos_ref(from_gw, source_rect) = spec_scen_g.find_graphic(need_pic, isParty);
		} else if(pic >= 100) {
			// Note that we assume it's a 1x1 graphic.
			// PCs can't be larger than that, but we leave it to the scenario designer to avoid assigning larger graphics.
			pic_num_t need_pic = pic - 100;
			int mode = 0;
			if(univ.party.direction >= 4)
				mode++;
			source_rect = get_monster_template_rect(need_pic, mode, 0);
			int which_sheet = m_pic_index[need_pic].i / 20;
			from_gw = ResMgr::get<ImageRsrc>("monst" + std::to_string(1 + which_sheet)).get();
		} else {
			source_rect = calc_rect(2 * (pic / 8), pic % 8);
			if(univ.party.direction >= 4)
				source_rect.offset(28,0);
			from_gw = ResMgr::get<ImageRsrc>("pcs").get();
		}
		ter_num_t ter = 0;
		if(is_out())
			ter = univ.out[univ.party.p_loc.x][univ.party.p_loc.y];
		else if(is_town() || is_combat())
			ter = univ.town->terrain(univ.town.p_loc.x,univ.town.p_loc.y);
		// now wedge in bed graphic
		if(is_town() && univ.scenario.ter_types[ter].special == eTerSpec::BED)
			draw_one_terrain_spot((short) target.x,(short) target.y,10000 + univ.scenario.ter_types[ter].flag1);
		else Draw_Some_Item(*from_gw, source_rect, terrain_screen_gworld, target, 1, 0);
	}
	else if(univ.party.in_boat >= 0) {
		if(univ.party.direction == DIR_N) i = 2;
		else if(univ.party.direction == DIR_S) i = 3;
		else i = univ.party.direction > DIR_S;
		Draw_Some_Item(*ResMgr::get<ImageRsrc>("vehicle"), calc_rect(i,0), terrain_screen_gworld, target, 1, 0);
	}else {
		i = univ.party.direction > 3;
		Draw_Some_Item(*ResMgr::get<ImageRsrc>("vehicle"), calc_rect(i + 2, 1), terrain_screen_gworld, target, 1, 0);
	}
}
Beispiel #15
0
void draw_monsters() {
	short i,j = 0,k;
	short width,height;
	rectangle source_rect,to_rect;
	location where_draw,store_loc;
	ter_num_t ter;
	rectangle monst_rects[4][4] = {
		{{0,0,36,28}},
		{{0,7,18,21},{18,7,36,21}},
		{{9,0,27,14},{9,14,27,28}},
		{{0,0,18,14},{0,14,18,28},{18,0,36,14},{18,14,36,28}}
	};
	
	if(is_out())
		for(i = 0; i < 10; i++)
			if(univ.party.out_c[i].exists) {
				if((point_onscreen(univ.party.p_loc, univ.party.out_c[i].m_loc)) &&
					(can_see_light(univ.party.p_loc, univ.party.out_c[i].m_loc,sight_obscurity) < 5)) {
					where_draw.x = univ.party.out_c[i].m_loc.x - univ.party.p_loc.x + 4;
					where_draw.y = univ.party.out_c[i].m_loc.y - univ.party.p_loc.y + 4;
					
					for(j = 0; univ.party.out_c[i].what_monst.monst[j] == 0 && j < 7; j++);
					
					short picture_wanted;
					if(j == 7) univ.party.out_c[i].exists = false; // begin watch out
					else {
						picture_wanted = get_monst_picnum(univ.party.out_c[i].what_monst.monst[j]);
					} // end watch out
					
					if(univ.party.out_c[i].exists) {
						get_monst_dims(univ.party.out_c[i].what_monst.monst[j],&width,&height);
						if(picture_wanted >= 1000) {
							for(k = 0; k < width * height; k++) {
								sf::Texture* src_gw;
								graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic(picture_wanted % 1000 +
																							 ((univ.party.out_c[i].direction < 4) ? 0 : (width * height)) + k);
								to_rect = monst_rects[(width - 1) * 2 + height - 1][k];
								to_rect.offset(13 + 28 * where_draw.x,13 + 36 * where_draw.y);
								rect_draw_some_item(*src_gw, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha);
							}
						}
						if(picture_wanted < 1000) {
							for(k = 0; k < width * height; k++) {
								source_rect = get_monster_template_rect(picture_wanted,(univ.party.out_c[i].direction < 4) ? 0 : 1,k);
								to_rect = monst_rects[(width - 1) * 2 + height - 1][k];
								to_rect.offset(13 + 28 * where_draw.x,13 + 36 * where_draw.y);
								int which_sheet = m_pic_index[picture_wanted].i / 20;
								sf::Texture& monst_gworld = *ResMgr::get<ImageRsrc>("monst" + std::to_string(1 + which_sheet));
								rect_draw_some_item(monst_gworld, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha);
							}
						}
					}
				}
			}
	if(is_town() || is_combat()) {
		for(i = 0; i < univ.town.monst.size(); i++)
			if(univ.town.monst[i].active != 0 && !univ.town.monst[i].invisible && univ.town.monst[i].status[eStatus::INVISIBLE] <= 0)
				if(point_onscreen(center,univ.town.monst[i].cur_loc) && party_can_see_monst(i)) {
					where_draw.x = univ.town.monst[i].cur_loc.x - center.x + 4;
					where_draw.y = univ.town.monst[i].cur_loc.y - center.y + 4;
					get_monst_dims(univ.town.monst[i].number,&width,&height);
					
					for(k = 0; k < width * height; k++) {
						store_loc = where_draw;
						store_loc.x += k % width;
						store_loc.y += k / width;
						ter = univ.town->terrain(univ.town.monst[i].cur_loc.x,univ.town.monst[i].cur_loc.y);
						// in bed?
						if(store_loc.x >= 0 && store_loc.x < 9 && store_loc.y >= 0 && store_loc.y < 9 &&
						   (univ.scenario.ter_types[ter].special == eTerSpec::BED) && isHumanoid(univ.town.monst[i].m_type)
						   && (univ.town.monst[i].active == 1 || univ.town.monst[i].target == 6) &&
						   width == 1 && height == 1)
							draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10000 + univ.scenario.ter_types[ter].flag1);
						else if(univ.town.monst[i].picture_num >= 1000) {
							bool isParty = univ.town.monst[i].picture_num >= 10000;
							sf::Texture* src_gw;
							pic_num_t need_pic = (univ.town.monst[i].picture_num % 1000) + k;
							if(univ.town.monst[i].direction >= 4) need_pic += width * height;
							if(combat_posing_monster == i + 100) need_pic += (2 * width * height);
							graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic(need_pic, isParty);
							Draw_Some_Item(*src_gw, source_rect, terrain_screen_gworld, store_loc, 1, 0);
						} else {
							pic_num_t this_monst = univ.town.monst[i].picture_num;
							int pic_mode = (univ.town.monst[i].direction) < 4 ? 0 : 1;
							pic_mode += (combat_posing_monster == i + 100) ? 10 : 0;
							source_rect = get_monster_template_rect(this_monst, pic_mode, k);
							int which_sheet = m_pic_index[this_monst].i / 20;
							sf::Texture& monst_gworld = *ResMgr::get<ImageRsrc>("monst" + std::to_string(1 + which_sheet));
							Draw_Some_Item(monst_gworld, source_rect, terrain_screen_gworld, store_loc, 1, 0);
						}
					}
				}
	}
}
Beispiel #16
0
short can_see_light(location p1, location p2, std::function<short(short,short)> get_obscurity) {
	if(is_combat() && !combat_pt_in_light(p2)) return 6;
	else if(is_town() && !pt_in_light(p1,p2)) return 6;
	return can_see(p1, p2, get_obscurity);
}