rebalanced various scenarios; fixed bug with roles not working properly

This commit is contained in:
Dave White 2004-06-26 20:57:49 +00:00
parent b70abe456c
commit 8997cfc402
46 changed files with 212 additions and 279 deletions

View file

@ -1083,6 +1083,7 @@
# XXX Campaigns separation not enabled in 0.7.10-CVS for backward compatibility
# of savegames. To be enabled sometime in the future...
# ifdef CAMPAIGN_HEIR_TO_THE_THRONE
{scenarios/Heir_To_The_Throne_Map.cfg}
{scenarios/Heir_To_The_Throne}
# endif
# ifdef CAMPAIGN_THE_DARK_HORDES

View file

@ -1,7 +1,7 @@
[scenario]
name="A Choice Must Be Made"
map_data="{maps/Heir_To_The_Throne/A_Choice_Must_Be_Made}"
turns=40
turns=30
id=A_Choice_Must_Be_Made
@ -12,6 +12,8 @@
{FIRST_WATCH}
{SECOND_WATCH}
{BIGMAP_A_CHOICE_MUST_BE_MADE}
objectives="
Victory:
@Defeat either of the enemy leaders
@ -51,7 +53,7 @@ Defeat:
side=3
controller=ai
canrecruit=1
{GOLD 250 300 500}
{GOLD 150 250 400}
#ifdef EASY
recruit=Skeleton,Revenant,Chocobone,Blood Bat,Ghost,Bone Shooter

View file

@ -24,6 +24,8 @@ Defeat:
#Death of Konrad
#Turns run out"
{BIGMAP_BAY_OF_PEARLS}
[bigmap]
image=misc/map.png
{DOT 188 414}

View file

@ -11,6 +11,8 @@
{FIRST_WATCH}
{SECOND_WATCH}
{BIGMAP_BLACKWATER_PORT}
turns=12
id=Blackwater_Port
@ -25,16 +27,7 @@ Defeat:
#Death of Delfador
#Death of Sir Kaylan"
[bigmap]
image=misc/map.png
{DOT 250 341}
{DOT 242 337}
{DOT 234 341}
{DOT 226 345}
{DOT 221 354}
{DOT 219 364}
{CROSS 219 377}
[/bigmap]
{BIGMAP_BLACKWATER_PORT}
[label]
x,y=26,8

View file

@ -14,14 +14,7 @@ Defeat:
#Death of Delfador
#Death of Kalenz"
[bigmap]
image=misc/map.png
{DOT 128 297}
{DOT 144 292}
{DOT 154 284}
{DOT 173 283}
{CROSS 189 282}
[/bigmap]
{BIGMAP_CROSSROADS}
{DAWN}
{MORNING}

View file

@ -15,10 +15,7 @@
music="wesnoth-4.ogg"
[bigmap]
image=misc/map.png
{CROSS 378 140}
[/bigmap]
{BIGMAP_DWARVEN_DOORS}
objectives="
Victory:

View file

@ -7,13 +7,13 @@ ffffffffffccffffffff
fffffffffffcffffffff
fffffffffffcffffffff
fffffffffffccfffffff
ffffffffffvfcfffffff
fffffffvCCCfcfffffff
ffffffCCC1Cvcfffffff
fffffffffftfcfffffff
ffffffftCCCfcfffffff
ffffffCCC1Ctcfffffff
ffffffC2CCCfcfffffff
fffffvCCC3Cvcfffffff
fffffffCCvCfcfffffff
fffffffvffffcfffffff
ffffftCCC3Ctcfffffff
fffffffCCtCfcfffffff
ffffffftffffcfffffff
ffffffffffffcfffffff
ffffffffffffccffffff
fffffffffffffcffffff
@ -30,6 +30,8 @@ fffffffffffffcffffff"
id=Elven_Council
next_scenario=valley_statue
{BIGMAP_HOME_OF_THE_NORTH_ELVES}
{DAWN}
{MORNING}
{AFTERNOON}
@ -309,7 +311,7 @@ fffffffffffffcffffff"
message="All routes are dangerous, though there is some hope along this path. Rest, and then go forth, friends. Fortune has smiled upon you so far, despite great dangers. Perhaps she will continue to do so."
[/message]
[endlevel]
result=continue
result=continue_no_save
[/endlevel]
[/event]
[/scenario]

View file

@ -24,19 +24,7 @@ Defeat:
#Death of Delfador
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 406 311}
{DOT 387 313}
{DOT 369 318}
{DOT 353 320}
{DOT 340 322}
{DOT 326 322}
{DOT 309 326}
{DOT 291 328}
{DOT 272 338}
{CROSS 259 352}
[/bigmap]
{BIGMAP_ELVES_BESIEGED}
{STARTING_VILLAGES 5 10}
{STARTING_VILLAGES 6 10}

View file

@ -15,13 +15,7 @@
music="wesnoth-2.ogg"
[bigmap]
image=misc/map.png
{DOT 305 202}
{DOT 313 195}
{DOT 321 188}
{CROSS 321 182}
[/bigmap]
{BIGMAP_FORD_OF_ABEZ}
objectives="
Victory:

View file

@ -23,18 +23,7 @@ Defeat:
#Death of Delfador
#Death of Kalenz"
[bigmap]
image=misc/map.png
[dot]
{DOT 262 225}
{DOT 272 214}
{DOT 288 207}
{CROSS 298 208}
type=cross
x=187
y=187
[/dot]
[/bigmap]
{BIGMAP_GRYPHON_MOUNTAIN}
[item]
x=10

View file

@ -19,14 +19,7 @@ Defeat:
#Death of Kalenz
#Death of Li'sar"
[bigmap]
image=misc/map.png
[dot]
type=cross
x=127
y=226
[/dot]
[/bigmap]
{BIGMAP_HASTY_ALLIANCE}
[side]
type=Commander

View file

@ -24,12 +24,7 @@ Defeat:
#Death of Li'sar
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 336 180}
{DOT 344 174}
{CROSS 354 167}
[/bigmap]
{BIGMAP_TEST_OF_THE_CLANS}
[side]
team_name=elves

View file

@ -10,7 +10,7 @@
{FIRST_WATCH}
{SECOND_WATCH}
turns=30
turns=18
id=North_Elves
next_scenario=Elven_Council
@ -24,12 +24,7 @@ Defeat:
#Death of Li'sar
#Turns run out before reaching the forest"
[bigmap]
image=misc/map.png
{DOT 336 180}
{DOT 344 174}
{CROSS 354 167}
[/bigmap]
{BIGMAP_HOME_OF_THE_NORTH_ELVES}
[side]
team_name=elves
@ -52,6 +47,16 @@ Defeat:
[ai]
recruitment_pattern=scout,scout,fighter,fighter,archer
[/ai]
[ai]
time_of_day=dusk
aggression=0.7
caution=0.25
[/ai]
[ai]
time_of_day=first_watch,second_watch
aggression=1.0
caution=0.0
[/ai]
{GOLD 200 300 400}
{INCOME 20 20 30}
[/side]
@ -80,6 +85,16 @@ Defeat:
value=100
[/target]
[/ai]
[ai]
time_of_day=dawn
aggression=0.7
caution=0.25
[/ai]
[ai]
time_of_day=morning,afternoon
aggression=1.0
caution=0.0
[/ai]
{GOLD 200 300 400}
{INCOME 15 30 40}

View file

@ -31,14 +31,7 @@ Defeat:
#Death of Delfador
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 219 377}
{DOT 217 385}
{DOT 211 390}
{DOT 205 395}
{CROSS 198 401}
[/bigmap]
{BIGMAP_ISLE_OF_ANDUIN}
[side]
race=Elves

View file

@ -23,18 +23,8 @@ Defeat:
disallow_recall=yes
[bigmap]
image=misc/map.png
{DOT 162 367}
{DOT 158 372}
{DOT 151 379}
{DOT 137 385}
{DOT 122 383}
{DOT 109 377}
{DOT 99 369}
{DOT 94 374}
{CROSS 93 386}
[/bigmap]
{BIGMAP_ISLES_OF_THE_DAMNED}
[item]
x=6

View file

@ -15,12 +15,7 @@
music="wesnoth-6.ogg"
[bigmap]
image=misc/map.png
{DOT 354 167}
{DOT 355 157}
{CROSS 356 147}
[/bigmap]
{BIGMAP_MOUNTAIN_PASS}
objectives="
Victory:

View file

@ -22,14 +22,7 @@ Defeat:
#Death of Konrad
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 164 348}
{DOT 158 340}
{DOT 142 338}
{DOT 127 340}
{CROSS 122 331}
[/bigmap]
{BIGMAP_MUFF_MALAL_PENINSULA}
[side]
race=Elves

View file

@ -24,12 +24,7 @@ Defeat:
#Death of Kalenz
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 336 180}
{DOT 344 174}
{CROSS 354 167}
[/bigmap]
{BIGMAP_MUFF_MALAL_PENINSULA}
[side]
race=Elves

View file

@ -10,14 +10,7 @@
music="underground.ogg"
[bigmap]
image=misc/map.png
[dot]
type=cross
x=187
y=187
[/dot]
[/bigmap]
{BIGMAP_PLUNGING_INTO_THE_DARKNESS}
objectives="
Victory:

View file

@ -36,15 +36,7 @@ Defeat:
#Death of Kalenz
#Turns run out"
[bigmap]
image=misc/map.png
{DOT 189 282}
{DOT 205 282}
{DOT 219 280}
{DOT 231 274}
{DOT 240 270}
{CROSS 250 264}
[/bigmap]
{BIGMAP_PRINCESS_OF_WESNOTH}
[label]
x,y=12,16

View file

@ -25,9 +25,7 @@ Defeat:
{deaths.cfg}
[bigmap]
image=misc/map.png
[/bigmap]
{BIGMAP_RETURN_TO_WESNOTH}
[side]
type=Commander

View file

@ -29,14 +29,7 @@ Defeat:
#Death of Kalenz
#Death of Li'sar"
[bigmap]
image=misc/map.png
[dot]
type=cross
x=127
y=226
[/dot]
[/bigmap]
{BIGMAP_SCEPTER_OF_FIRE}
[event]
name=start

View file

@ -13,6 +13,8 @@
{FIRST_WATCH}
{SECOND_WATCH}
{BIGMAP_SNOW_PLAINS}
objectives="
Victory:
@Defeat enemy leader

View file

@ -1,7 +1,7 @@
[scenario]
name="Swamp Of Dread"
map_data="{maps/Heir_To_The_Throne/Swamp_Of_Dread}"
turns=40
turns=30
id=Swamp_Of_Dread
next_scenario="North_Elves"
@ -13,6 +13,8 @@
{FIRST_WATCH}
{SECOND_WATCH}
{BIGMAP_SWAMP_OF_DREAD}
objectives="
Victory:
@Defeat all enemy leaders
@ -33,6 +35,20 @@ Defeat
hitpoints=80
[/side]
#define SWAMP_DREAD_AI_PARAMS
[ai]
time_of_day=dusk
turns=8-100
caution=0.25
aggression=0.8
[/ai]
[ai]
time_of_day=first_watch,second_watch
caution=0.0
aggression=1.0
[/ai]
#enddef
[side]
type=Death Knight
description=Clarustus
@ -44,6 +60,7 @@ Defeat
[ai]
{NO_SCOUTS}
[/ai]
{SWAMP_DREAD_AI_PARAMS}
team_name=undead
[/side]
@ -55,6 +72,7 @@ Defeat
canrecruit=1
recruit=Ghost,Skeleton,Walking Corpse
{GOLD 100 200 300}
{SWAMP_DREAD_AI_PARAMS}
team_name=undead
[/side]
@ -67,6 +85,7 @@ Defeat
recruit=Wraith,Vampire Bat,Skeleton
{GOLD 100 200 300}
team_name=undead
{SWAMP_DREAD_AI_PARAMS}
[/side]
[side]
@ -79,6 +98,7 @@ Defeat
[ai]
{NO_SCOUTS}
[/ai]
{SWAMP_DREAD_AI_PARAMS}
{GOLD 80 150 200}
team_name=undead
[/side]
@ -92,6 +112,7 @@ Defeat
recruit=Skeleton Archer,Walking Corpse,Ghost
{GOLD 80 150 200}
team_name=undead
{SWAMP_DREAD_AI_PARAMS}
[/side]
[event]
@ -115,66 +136,5 @@ Defeat
description=Konrad
message="The Liches are all over this swamp. I hope I have made a wise choice in taking this path."
[/message]
[message]
id=msgswamp3
description=Delfador
message="Each of the Liches will have a pile of gold you can take, if they are defeated. Do not stretch your armies too thin, for we still must pass through this swamp."
[/message]
[/event]
#define SWAMP_GET_GOLD AMOUNT
[command]
[gold]
side=1
amount={AMOUNT}
[/gold]
[/command]
[command]
[message]
id=msg_get_gold_swamp
speaker=narrator
message="You loot {AMOUNT} pieces of gold from the corpse!"
[/message]
[/command]
#enddef
[event]
name=die
[filter]
description=Clarustus
[/filter]
{SWAMP_GET_GOLD 100}
[/event]
[event]
name=die
[filter]
description=Merlunius
[/filter]
{SWAMP_GET_GOLD 100}
[/event]
[event]
name=die
[filter]
description=Aimucasur
[/filter]
{SWAMP_GET_GOLD 150}
[/event]
[event]
name=die
[filter]
description=Secadius
[/filter]
{SWAMP_GET_GOLD 100}
[/event]
[event]
name=die
[filter]
description=Dafeis
[/filter]
{SWAMP_GET_GOLD 100}
[/event]
[/scenario]

View file

@ -10,14 +10,7 @@
music="underground.ogg"
[bigmap]
image=misc/map.png
[dot]
type=cross
x=187
y=187
[/dot]
[/bigmap]
{BIGMAP_THE_LOST_GENERAL}
objectives="
Victory:

View file

@ -28,13 +28,7 @@ Defeat:
id=elensefar
[/label]
[bigmap]
image=misc/map.png
{DOT 131 332}
{DOT 127 320}
{DOT 123 309}
{CROSS 118 299}
[/bigmap]
{BIGMAP_SIEGE_OF_ELENSEFAR}
[side]
type=Commander

View file

@ -23,13 +23,7 @@ Defeat:
#Death of Delfador
#Death of Kalenz"
[bigmap]
image=misc/map.png
{DOT 250 255}
{DOT 251 246}
{DOT 253 239}
{CROSS 253 231}
[/bigmap]
{BIGMAP_VALLEY_OF_DEATH}
[side]
type=Commander

View file

@ -85,6 +85,7 @@ Defeat:
{FIRST_WATCH}
{SECOND_WATCH}
{BIGMAP_VALLEY_OF_STATUES}
# Monster in cave
[item]
@ -143,6 +144,10 @@ Defeat:
[ai]
recruitment_pattern=fighter,scout
{NO_SCOUTS}
recruitment_ignore_bad_combat=yes
recruitment_ignore_bad_movement=yes
caution=0.25
aggression=0.75
[/ai]
recruit=Cockatrice,Vampire Bat
gold=100
@ -159,9 +164,13 @@ Defeat:
[ai]
recruitment_pattern=fighter,scout
{NO_SCOUTS}
recruitment_ignore_bad_combat=yes
recruitment_ignore_bad_movement=yes
caution=0.25
aggression=0.75
[/ai]
recruit=Cockatrice,Gryphon
gold=100
gold=200
{INCOME 10 20 30}
team_name=bad
[/side]

View file

@ -39,7 +39,7 @@ height=600
[menu]
is_context_menu=true
items=undo,redo,cycle,describeunit,speak,continue,recruit,recall,createunit,renameunit,labelterrain,showenemymoves,bestenemymoves,delayshroud,updateshroud,endturn
items=undo,redo,cycle,describeunit,speak,continue,recruit,recall,createunit,changeside,renameunit,labelterrain,showenemymoves,bestenemymoves,delayshroud,updateshroud,endturn
[/menu]
# top panel

View file

@ -530,6 +530,7 @@ action_unitlist="Unit List"
action_objectives="Scenario Objectives"
action_preferences="Preferences"
action_createunit="Create Unit (Debug!)"
action_changeside="Change Unit Side (Debug!)"
action_speak="Speak"
action_zoomin="Zoom In"
action_zoomout="Zoom Out"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 624 KiB

View file

@ -252,6 +252,9 @@ battle_stats evaluate_battle_stats(
res.attack_name = attack.name();
res.attack_type = attack.type();
static const std::string slow_string("slow");
res.attacker_slows = attack.special() == slow_string;
if(include_strings) {
res.attack_special = attack.special();
res.attack_icon = attack.icon();
@ -402,6 +405,7 @@ battle_stats evaluate_battle_stats(
}
res.defender_plague = (defender_attacks[defend].special() == plague_string);
res.defender_slows = (defender_attacks[defend].special() == slow_string);
static const std::string first_strike = "firststrike";
res.defender_strikes_first = defender_attacks[defend].special() == first_strike && attack.special() != first_strike;
@ -678,9 +682,7 @@ void attack(display& gui, const gamemap& map,
d->second.set_flag("poisoned");
}
static const std::string slow_string("slow");
if(stats.attack_special == slow_string &&
d->second.has_flag("slowed") == false) {
if(stats.attacker_slows && d->second.has_flag("slowed") == false) {
gui.float_label(d->first,translate_string("slowed"),255,0,0);
d->second.set_flag("slowed");
if(stats.ndefends > 1)
@ -816,9 +818,7 @@ void attack(display& gui, const gamemap& map,
a->second.set_flag("poisoned");
}
static const std::string slow_string("slow");
if(stats.defend_special == slow_string &&
a->second.has_flag("slowed") == false) {
if(stats.defender_slows && a->second.has_flag("slowed") == false) {
gui.float_label(a->first,translate_string("slowed"),255,0,0);
a->second.set_flag("slowed");
if(stats.nattacks > 1)

View file

@ -58,6 +58,7 @@ struct battle_stats
int ndefends, nattacks;
int attack_with, defend_with;
bool attacker_plague, defender_plague;
bool attacker_slows, defender_slows;
std::vector<std::string> attack_calculations, defend_calculations;
bool to_the_death, defender_strikes_first;
};

View file

@ -76,13 +76,21 @@ void ai::do_attack_analysis(
//see if the unit has the backstab ability -- units with backstab
//will want to try to have a friendly unit opposite the position they move to
bool backstab = false;
//see if the unit has the slow ability -- units with slow only attack first
bool backstab = false, slow = false;
const std::vector<attack_type>& attacks = unit_itor->second.attacks();
for(std::vector<attack_type>::const_iterator a = attacks.begin(); a != attacks.end(); ++a) {
if(a->backstab()) {
backstab = true;
break;
}
if(a->slow()) {
slow = true;
}
}
if(slow && cur_analysis.movements.empty() == false) {
continue;
}
double best_vulnerability = 0.0, best_support = 0.0;
@ -352,6 +360,8 @@ void ai::attack_analysis::analyze(const gamemap& map,
int defenderxp = 0;
bool defender_slowed = false;
int defhp = target_hp;
for(size_t i = 0; i != movements.size() && defhp; ++i) {
const battle_stats& stat = stats[i];
@ -360,6 +370,13 @@ void ai::attack_analysis::analyze(const gamemap& map,
int attacks = stat.nattacks;
int defends = stat.ndefends;
if(defender_slowed && defends > 1) {
--defends;
//give an extra bonus based on slowing here
avg_damage_taken -= stat.damage_defender_takes;
}
unit_map::const_iterator att = units.find(movements[i].first);
double cost = att->second.type().cost();
@ -389,8 +406,13 @@ void ai::attack_analysis::analyze(const gamemap& map,
}
atthp += stat.amount_attacker_drains;
if(atthp > hitpoints[i])
if(atthp > hitpoints[i]) {
atthp = hitpoints[i];
}
if(stat.attacker_slows && !defender_slowed && defend_it->second.has_flag("slowed") == false) {
defender_slowed = true;
}
}
--attacks;
@ -413,8 +435,9 @@ void ai::attack_analysis::analyze(const gamemap& map,
}
defhp += stat.amount_defender_drains;
if(defhp > target_max_hp)
if(defhp > target_max_hp) {
defhp = target_max_hp;
}
}
--defends;

View file

@ -212,6 +212,12 @@ void cave_map_generator::place_items(const chamber& c, config::all_children_iter
const std::string& key = *(*i1).first;
config cfg = *(*i1).second;
config* const filter = cfg.child("filter");
config* const object = cfg.child("object");
config* object_filter = NULL;
if(object != NULL) {
object_filter = object->child("filter");
}
if(cfg["same_location_as_previous"] != "yes") {
index = rand()%c.locs.size();
}
@ -226,12 +232,20 @@ void cave_map_generator::place_items(const chamber& c, config::all_children_iter
(*filter)["x"] = buf;
}
if(object_filter != NULL) {
(*object_filter)["x"] = buf;
}
sprintf(buf,"%d",loc->y+1);
cfg.values["y"] = buf;
if(filter != NULL) {
(*filter)["y"] = buf;
}
if(object_filter != NULL) {
(*object_filter)["y"] = buf;
}
//if this is a side, place a castle for the side
if(key == "side" && cfg["no_castle"] != "yes") {
place_castle(cfg["side"],*loc);

View file

@ -194,7 +194,15 @@ std::string get_dir(const std::string& dir_path)
std::string get_user_data_dir()
{
#ifdef _WIN32
_mkdir("userdata");
static bool inited_dirs = false;
if(!inited_dirs) {
_mkdir("userdata");
_mkdir("userdata/editor");
_mkdir("userdata/editor/maps");
inited_dirs = true;
}
char buf[256];
const char* const res = getcwd(buf,sizeof(buf));
@ -224,6 +232,10 @@ std::string get_user_data_dir()
DIR* dir = opendir(dir_path.c_str());
if(dir == NULL) {
const int res = mkdir(dir_path.c_str(),AccessMode);
//also create the maps directory
mkdir((dir_path + "/editor").c_str(),AccessMode);
mkdir((dir_path + "/editor/maps").c_str(),AccessMode);
if(res == 0) {
dir = opendir(dir_path.c_str());
} else {

View file

@ -594,6 +594,7 @@ bool event_handler::handle_event_command(const queued_event& event_info, const s
for(ti = types.begin(); ti != types.end(); ++ti) {
config item = cfg;
item["type"] = *ti;
item["role"] = "";
std::map<gamemap::location,unit>::iterator itor;
for(itor = units->begin(); itor != units->end(); ++itor) {

View file

@ -61,6 +61,7 @@ HOTKEY_COMMAND string_to_command(const std::string& str)
m.insert(val("mute",HOTKEY_MUTE));
m.insert(val("speak",HOTKEY_SPEAK));
m.insert(val("createunit",HOTKEY_CREATE_UNIT));
m.insert(val("changeside",HOTKEY_CHANGE_UNIT_SIDE));
m.insert(val("preferences",HOTKEY_PREFERENCES));
m.insert(val("objectives",HOTKEY_OBJECTIVES));
m.insert(val("unitlist",HOTKEY_UNIT_LIST));
@ -431,6 +432,10 @@ void execute_command(display& disp, HOTKEY_COMMAND command, command_executor* ex
if(executor)
executor->create_unit();
break;
case HOTKEY_CHANGE_UNIT_SIDE:
if(executor)
executor->change_unit_side();
break;
case HOTKEY_PREFERENCES:
if(executor)
executor->preferences();

View file

@ -31,7 +31,7 @@ enum HOTKEY_COMMAND { HOTKEY_CYCLE_UNITS, HOTKEY_END_UNIT_TURN, HOTKEY_LEADER,
HOTKEY_UNIT_DESCRIPTION, HOTKEY_RENAME_UNIT, HOTKEY_SAVE_GAME, HOTKEY_LOAD_GAME,
HOTKEY_RECRUIT, HOTKEY_REPEAT_RECRUIT, HOTKEY_RECALL, HOTKEY_ENDTURN,
HOTKEY_TOGGLE_GRID, HOTKEY_STATUS_TABLE, HOTKEY_MUTE,
HOTKEY_SPEAK, HOTKEY_CREATE_UNIT, HOTKEY_PREFERENCES,
HOTKEY_SPEAK, HOTKEY_CREATE_UNIT, HOTKEY_CHANGE_UNIT_SIDE, HOTKEY_PREFERENCES,
HOTKEY_OBJECTIVES, HOTKEY_UNIT_LIST, HOTKEY_STATISTICS, HOTKEY_QUIT_GAME,
HOTKEY_LABEL_TERRAIN, HOTKEY_SHOW_ENEMY_MOVES, HOTKEY_BEST_ENEMY_MOVES,
HOTKEY_DELAY_SHROUD, HOTKEY_UPDATE_SHROUD, HOTKEY_CONTINUE_MOVE,
@ -110,6 +110,7 @@ public:
virtual void repeat_recruit() {}
virtual void speak() {}
virtual void create_unit() {}
virtual void change_unit_side() {}
virtual void preferences() {}
virtual void objectives() {}
virtual void unit_list() {}

View file

@ -6,6 +6,7 @@
#include <algorithm>
#include <cassert>
#include <cerrno>
#include <queue>
#include <iostream>
#include <set>
@ -20,11 +21,10 @@ namespace {
//the same, so it's all seamless to the user
struct connection_details {
connection_details(TCPsocket sock, const std::string& host, int port)
: sock(sock), disconnected_at(0), host(host), port(port), remote_handle(0)
: sock(sock), host(host), port(port), remote_handle(0)
{}
TCPsocket sock;
int disconnected_at;
std::string host;
int port;
@ -193,6 +193,8 @@ connection connect(const std::string& host, int port)
TCPsocket sock = SDLNet_TCP_Open(&ip);
if(!sock) {
throw error("Could not connect to host");
} else {
//TODO: add code in here which sets the socket to non-blocking
}
//if this is a server socket
@ -531,31 +533,15 @@ void send_data(const config& cfg, connection connection_num, size_t max_size, SE
SDLNet_Write32(value.size()+1-4,buf);
std::copy(buf,buf+4,value.begin());
//if the data is less than our maximum chunk, and there is no data queued to send
//to this host, then send all data now
if(mode == SEND_DATA && (max_size == 0 || value.size()+1 <= max_size) && send_queue.count(connection_num) == 0) {
std::cerr << "sending " << (value.size()+1) << " bytes\n";
const int res = SDLNet_TCP_Send(get_socket(connection_num),
const_cast<char*>(value.c_str()),
value.size()+1);
//place the data in the send queue
const send_queue_map::iterator itor = send_queue.insert(std::pair<network::connection,partial_buffer>(connection_num,partial_buffer()));
if(res != int(value.size()+1)) {
std::cerr << "sending data failed: " << res << "/" << value.size() << "\n";
throw error("Could not send data over socket",connection_num);
}
} else {
std::cerr << "cannot send all " << (value.size()+1) << " bytes at once. Placing in send queue.\n";
//place the data in the send queue
const send_queue_map::iterator itor =
send_queue.insert(std::pair<network::connection,partial_buffer>(connection_num,partial_buffer()));
itor->second.buf.resize(value.size()+1);
std::copy(value.begin(),value.end(),itor->second.buf.begin());
itor->second.buf.back() = 0;
itor->second.buf.resize(value.size()+1);
std::copy(value.begin(),value.end(),itor->second.buf.begin());
itor->second.buf.back() = 0;
if(mode == SEND_DATA) {
process_send_queue(connection_num,max_size);
}
if(mode == SEND_DATA) {
process_send_queue(connection_num,max_size);
}
}
@ -597,14 +583,14 @@ void process_send_queue(connection connection_num, size_t max_size)
std::cerr << "sending " << bytes_to_send << " from send queue\n";
const int res = SDLNet_TCP_Send(sock,&buf[upto],bytes_to_send);
if(res != int(bytes_to_send)) {
if(res < 0 || res != int(bytes_to_send) && errno != EAGAIN) {
std::cerr << "sending data failed: " << res << "/" << bytes_to_send << "\n";
throw error("Sending queued data failed",connection_num);
}
std::cerr << "sent.\n";
upto += bytes_to_send;
upto += res;
//if we've now sent the entire item, erase it from the send queue
if(upto == buf.size()) {

View file

@ -982,6 +982,7 @@ bool turn_info::can_execute_command(hotkey::HOTKEY_COMMAND command) const
//commands we can only do if in debug mode
case hotkey::HOTKEY_CREATE_UNIT:
case hotkey::HOTKEY_CHANGE_UNIT_SIDE:
return !commands_disabled && game_config::debug && map_.on_board(last_hex_);
default:
@ -1851,6 +1852,22 @@ void turn_info::create_unit()
}
}
void turn_info::change_unit_side()
{
const unit_map::iterator i = units_.find(last_hex_);
if(i == units_.end()) {
return;
}
int side = i->second.side();
++side;
if(side > team::nteams()) {
side = 1;
}
i->second.set_side(side);
}
void turn_info::preferences()
{
preferences::show_preferences_dialog(gui_);

View file

@ -141,6 +141,7 @@ private:
virtual void recall();
virtual void speak();
virtual void create_unit();
virtual void change_unit_side();
virtual void preferences();
virtual void objectives();
virtual void unit_list();

View file

@ -201,6 +201,11 @@ int unit::side() const
return side_;
}
void unit::set_side(int new_side)
{
side_ = new_side;
}
double unit::alpha() const
{
return type().alpha();

View file

@ -53,6 +53,7 @@ public:
bool get_experience(int xp);
bool advances() const;
int side() const;
void set_side(int new_side);
double alpha() const;
void make_recruiter();
bool can_recruit() const;

View file

@ -146,6 +146,7 @@ attack_type::attack_type(const config& cfg) : animation_(cfg)
type_ = cfg["type"];
special_ = cfg["special"];
backstab_ = special_ == "backstab";
slow_ = special_ == "slow";
icon_ = cfg["icon"];
if(icon_.empty())
icon_ = "attacks/" + name_ + ".png";
@ -218,6 +219,11 @@ bool attack_type::backstab() const
return backstab_;
}
bool attack_type::slow() const
{
return slow_;
}
bool attack_type::matches_filter(const config& cfg) const
{
const std::string& filter_range = cfg["range"];

View file

@ -94,6 +94,7 @@ public:
double defense_weight() const;
bool backstab() const;
bool slow() const;
const unit_animation& animation() const { return animation_; }
@ -112,9 +113,9 @@ private:
double attack_weight_;
double defense_weight_;
//caches whether the unit can backstab. This is important
//caches whether the unit can backstab and slow. This is important
//because the AI queries it alot.
bool backstab_;
bool backstab_, slow_;
};
class unit_movement_type;