summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/tags.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-18 07:05:07 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-18 07:05:07 +0000
commit3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1 (patch)
treea838b57e94a87f84fcdbf3e551b365aec922259d /crawl-ref/source/tags.cc
parentde11c27378236139089c48ecfb0b66457cc0d67c (diff)
downloadcrawl-ref-3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1.tar.gz
crawl-ref-3fdf3ab24ea63ecde6537ea122e2ab1cd6b8d4f1.zip
Banished uniques (including ghosts) will now be sent to the Abyss. Banished
non-uniques may also get the Abyss treatment if they clear a HD roll. Crawl tries very hard not to lose banished monsters, preserving them across Abyss shifts and teleports, and saving them on the transit list when the player escapes the Abyss. Breaks savefile compatibility. Toned down Vehumet and wizardry boosts a touch. Fixed bugginess where player could get aux unarmed attacks on a monster that just teleported away (by weapon of distortion). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1052 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/tags.cc')
-rw-r--r--crawl-ref/source/tags.cc358
1 files changed, 219 insertions, 139 deletions
diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc
index 63fe4fc70b..ebf7587c2c 100644
--- a/crawl-ref/source/tags.cc
+++ b/crawl-ref/source/tags.cc
@@ -76,6 +76,7 @@
#include "itemprop.h"
#include "monstuff.h"
#include "mon-util.h"
+#include "mtransit.h"
#include "randart.h"
#include "skills.h"
#include "skills2.h"
@@ -99,9 +100,11 @@ FixedArray < bool, MAX_LEVELS, NUM_BRANCHES > tmp_file_pairs;
static void tag_construct_you(struct tagHeader &th);
static void tag_construct_you_items(struct tagHeader &th);
static void tag_construct_you_dungeon(struct tagHeader &th);
+static void tag_construct_lost_monsters(tagHeader &th);
static void tag_read_you(struct tagHeader &th, char minorVersion);
static void tag_read_you_items(struct tagHeader &th, char minorVersion);
static void tag_read_you_dungeon(struct tagHeader &th);
+static void tag_read_lost_monsters(tagHeader &th, int minorVersion);
static void tag_construct_level(struct tagHeader &th);
static void tag_construct_level_items(struct tagHeader &th);
@@ -118,6 +121,10 @@ static void tag_read_ghost(struct tagHeader &th, char minorVersion);
static void marshallGhost(tagHeader &th, const ghost_demon &ghost);
static ghost_demon unmarshallGhost( tagHeader &th );
+static void marshall_monster(tagHeader &th, const monsters &m);
+static void unmarshall_monster(tagHeader &th, monsters &m);
+static void marshall_item(tagHeader &th, const item_def &item);
+static void unmarshall_item(tagHeader &th, item_def &item);
// provide a wrapper for file writing, just in case.
int write2(FILE * file, const char *buffer, unsigned int count)
@@ -219,10 +226,11 @@ void marshallMap(struct tagHeader &th, const std::map<key,value>& data,
}
}
-void marshall_level_id( struct tagHeader& th, const level_id& id )
+void marshall_level_id( tagHeader& th, const level_id& id )
{
marshallByte(th, id.branch );
marshallLong(th, id.depth );
+ marshallByte(th, id.level_type);
}
void marshall_level_pos( struct tagHeader& th, const level_pos& lpos )
@@ -234,17 +242,15 @@ void marshall_level_pos( struct tagHeader& th, const level_pos& lpos )
template<typename key, typename value>
void unmarshallMap(struct tagHeader& th, std::map<key,value>& data,
- key (*key_unmarshall) (struct tagHeader&),
- value (*value_unmarshall)(struct tagHeader&) )
+ key (*key_unmarshall) (tagHeader&),
+ value (*value_unmarshall)(tagHeader&) )
{
long i, len = unmarshallLong(th);
key k;
- value v;
for ( i = 0; i < len; ++i )
{
k = key_unmarshall(th);
- v = value_unmarshall(th);
- data[k] = v;
+ data[k] = value_unmarshall(th);
}
}
@@ -254,12 +260,13 @@ T unmarshall_long_as( struct tagHeader& th )
return static_cast<T>(unmarshallLong(th));
}
-level_id unmarshall_level_id( struct tagHeader& th )
+level_id unmarshall_level_id( tagHeader& th )
{
level_id id;
id.branch = unmarshallByte(th);
id.depth = unmarshallLong(th);
- return id;
+ id.level_type = unmarshallByte(th);
+ return (id);
}
level_pos unmarshall_level_pos( struct tagHeader& th )
@@ -267,7 +274,7 @@ level_pos unmarshall_level_pos( struct tagHeader& th )
level_pos lpos;
lpos.pos.x = unmarshallLong(th);
lpos.pos.y = unmarshallLong(th);
- lpos.id = unmarshall_level_id(th);
+ lpos.id = unmarshall_level_id(th);
return lpos;
}
@@ -459,6 +466,9 @@ void tag_construct(struct tagHeader &th, int tagID)
case TAG_GHOST:
tag_construct_ghost(th);
break;
+ case TAG_LOST_MONSTERS:
+ tag_construct_lost_monsters(th);
+ break;
default:
// I don't know how to make that!
break;
@@ -557,6 +567,9 @@ int tag_read(FILE *fp, char minorVersion)
case TAG_GHOST:
tag_read_ghost(th, minorVersion);
break;
+ case TAG_LOST_MONSTERS:
+ tag_read_lost_monsters(th, minorVersion);
+ break;
default:
// I don't know how to read that!
return 0;
@@ -602,8 +615,11 @@ void tag_set_expected(char tags[], int fileType)
switch(fileType)
{
case TAGTYPE_PLAYER:
- if (i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
+ if ((i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
+ || i == TAG_LOST_MONSTERS)
+ {
tags[i] = 1;
+ }
break;
case TAGTYPE_PLAYER_NAME:
if (i == TAG_YOU)
@@ -910,6 +926,53 @@ static void tag_construct_you_dungeon(struct tagHeader &th)
marshall_level_pos, marshall_as_long<portal_type>);
}
+static void marshall_follower(tagHeader &th, const follower &f)
+{
+ marshall_monster(th, f.mons);
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ marshall_item(th, f.items[i]);
+}
+
+static void unmarshall_follower(tagHeader &th, follower &f)
+{
+ unmarshall_monster(th, f.mons);
+ for (int i = 0; i < NUM_MONSTER_SLOTS; ++i)
+ unmarshall_item(th, f.items[i]);
+}
+
+static void marshall_follower_list(tagHeader &th, const m_transit_list &mlist)
+{
+ marshallShort( th, mlist.size() );
+
+ for (m_transit_list::const_iterator mi = mlist.begin();
+ mi != mlist.end(); ++mi)
+ {
+ marshall_follower( th, *mi );
+ }
+}
+
+static m_transit_list unmarshall_follower_list(tagHeader &th)
+{
+ m_transit_list mlist;
+
+ const int size = unmarshallShort(th);
+
+ for (int i = 0; i < size; ++i)
+ {
+ follower f;
+ unmarshall_follower(th, f);
+ mlist.push_back(f);
+ }
+
+ return (mlist);
+}
+
+static void tag_construct_lost_monsters(tagHeader &th)
+{
+ marshallMap( th, the_lost_ones, marshall_level_id,
+ marshall_follower_list );
+}
+
static void tag_read_you(struct tagHeader &th, char minorVersion)
{
char buff[20]; // For birth date
@@ -1200,7 +1263,8 @@ static void tag_read_you_dungeon(struct tagHeader &th)
}
unmarshallMap(th, stair_level,
- unmarshall_long_as<branch_type>, unmarshall_level_id);
+ unmarshall_long_as<branch_type>,
+ unmarshall_level_id);
unmarshallMap(th, shops_present,
unmarshall_level_pos, unmarshall_long_as<shop_type>);
unmarshallMap(th, altars_present,
@@ -1209,6 +1273,14 @@ static void tag_read_you_dungeon(struct tagHeader &th)
unmarshall_level_pos, unmarshall_long_as<portal_type>);
}
+static void tag_read_lost_monsters(tagHeader &th, int minorVersion)
+{
+ the_lost_ones.clear();
+
+ unmarshallMap(th, the_lost_ones,
+ unmarshall_level_id, unmarshall_follower_list);
+}
+
// ------------------------------- level tags ---------------------------- //
static void tag_construct_level(struct tagHeader &th)
@@ -1262,6 +1334,62 @@ static void tag_construct_level(struct tagHeader &th)
}
}
+static void marshall_item(tagHeader &th, const item_def &item)
+{
+ marshallByte(th, item.base_type);
+ marshallByte(th, item.sub_type);
+ marshallShort(th, item.plus);
+ marshallShort(th, item.plus2);
+ marshallLong(th, item.special);
+ marshallShort(th, item.quantity);
+
+ marshallByte(th, item.colour);
+ marshallShort(th, item.x);
+ marshallShort(th, item.y);
+ marshallLong(th, item.flags);
+
+ marshallShort(th, item.link); // unused
+ marshallShort(th, igrd[item.x][item.y]); // unused
+
+ marshallByte(th, item.slot);
+
+ marshallShort(th, item.orig_place);
+ marshallShort(th, item.orig_monnum);
+ marshallString(th, item.inscription.c_str(), 80);
+}
+
+static void unmarshall_item(tagHeader &th, item_def &item)
+{
+ item.base_type = (unsigned char) unmarshallByte(th);
+ item.sub_type = (unsigned char) unmarshallByte(th);
+ item.plus = unmarshallShort(th);
+ item.plus2 = unmarshallShort(th);
+ item.special = unmarshallLong(th);
+ item.quantity = unmarshallShort(th);
+ item.colour = (unsigned char) unmarshallByte(th);
+ item.x = unmarshallShort(th);
+ item.y = unmarshallShort(th);
+ item.flags = (unsigned long) unmarshallLong(th);
+
+ // [dshaligram] FIXME, remove this kludge when ARM_CAP is fully
+ // integrated.
+ if (item.base_type == OBJ_ARMOUR && item.sub_type == ARM_CAP)
+ item.sub_type = ARM_HELMET;
+
+ unmarshallShort(th); // mitm[].link -- unused
+ unmarshallShort(th); // igrd[item.x][item.y] -- unused
+
+ item.slot = unmarshallByte(th);
+ item.inscription.clear();
+
+ item.orig_place = unmarshallShort(th);
+ item.orig_monnum = unmarshallShort(th);
+
+ char insstring[80];
+ unmarshallString(th, insstring, 80);
+ item.inscription = std::string(insstring);
+}
+
static void tag_construct_level_items(struct tagHeader &th)
{
int i;
@@ -1278,37 +1406,53 @@ static void tag_construct_level_items(struct tagHeader &th)
// how many items?
marshallShort(th, MAX_ITEMS);
for (i = 0; i < MAX_ITEMS; ++i)
+ marshall_item(th, mitm[i]);
+}
+
+static void marshall_monster(tagHeader &th, const monsters &m)
+{
+ marshallByte(th, m.ac);
+ marshallByte(th, m.ev);
+ marshallByte(th, m.hit_dice);
+ marshallByte(th, m.speed);
+ marshallByte(th, m.speed_increment);
+ marshallByte(th, m.behaviour);
+ marshallByte(th, m.x);
+ marshallByte(th, m.y);
+ marshallByte(th, m.target_x);
+ marshallByte(th, m.target_y);
+ marshallLong(th, m.flags);
+
+ for (int j = 0; j < NUM_MON_ENCHANTS; j++)
+ marshallByte(th, m.enchantment[j]);
+
+ marshallShort(th, m.type);
+ marshallShort(th, m.hit_points);
+ marshallShort(th, m.max_hit_points);
+ marshallShort(th, m.number);
+ marshallShort(th, m.colour);
+
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ marshallShort(th, m.inv[j]);
+
+ for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ marshallShort(th, m.spells[j]);
+
+ marshallByte(th, m.god);
+
+ if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
{
- marshallByte(th, mitm[i].base_type);
- marshallByte(th, mitm[i].sub_type);
- marshallShort(th, mitm[i].plus);
- marshallShort(th, mitm[i].plus2);
- marshallLong(th, mitm[i].special);
- marshallShort(th, mitm[i].quantity);
-
- marshallByte(th, mitm[i].colour);
- marshallShort(th, mitm[i].x);
- marshallShort(th, mitm[i].y);
- marshallLong(th, mitm[i].flags);
-
- marshallShort(th, mitm[i].link); // unused
- marshallShort(th, igrd[mitm[i].x][mitm[i].y]); // unused
-
- marshallByte(th, mitm[i].slot);
-
- marshallShort(th, mitm[i].orig_place);
- marshallShort(th, mitm[i].orig_monnum);
- marshallString(th, mitm[i].inscription.c_str(), 80);
+ // *Must* have ghost field set.
+ ASSERT(m.ghost.get());
+ marshallGhost(th, *m.ghost);
}
}
static void tag_construct_level_monsters(struct tagHeader &th)
{
- int i,j;
-
// how many mons_alloc?
marshallByte(th, 20);
- for (i = 0; i < 20; ++i)
+ for (int i = 0; i < 20; ++i)
marshallShort(th, env.mons_alloc[i]);
// how many monsters?
@@ -1318,46 +1462,8 @@ static void tag_construct_level_monsters(struct tagHeader &th)
// how many monster inventory slots?
marshallByte(th, NUM_MONSTER_SLOTS);
- for (i = 0; i < MAX_MONSTERS; i++)
- {
- const monsters &m = menv[i];
-
- marshallByte(th, m.ac);
- marshallByte(th, m.ev);
- marshallByte(th, m.hit_dice);
- marshallByte(th, m.speed);
- marshallByte(th, m.speed_increment);
- marshallByte(th, m.behaviour);
- marshallByte(th, m.x);
- marshallByte(th, m.y);
- marshallByte(th, m.target_x);
- marshallByte(th, m.target_y);
- marshallLong(th, m.flags);
-
- for (j = 0; j < NUM_MON_ENCHANTS; j++)
- marshallByte(th, m.enchantment[j]);
-
- marshallShort(th, m.type);
- marshallShort(th, m.hit_points);
- marshallShort(th, m.max_hit_points);
- marshallShort(th, m.number);
- marshallShort(th, m.colour);
-
- for (j = 0; j < NUM_MONSTER_SLOTS; j++)
- marshallShort(th, m.inv[j]);
-
- for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
- marshallShort(th, m.spells[j]);
-
- marshallByte(th, m.god);
-
- if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
- {
- // *Must* have ghost field set.
- ASSERT(m.ghost.get());
- marshallGhost(th, *m.ghost);
- }
- }
+ for (int i = 0; i < MAX_MONSTERS; i++)
+ marshall_monster(th, menv[i]);
}
void tag_construct_level_attitude(struct tagHeader &th)
@@ -1450,41 +1556,49 @@ static void tag_read_level_items(struct tagHeader &th, char minorVersion)
// how many items?
count = unmarshallShort(th);
for (i = 0; i < count; ++i)
- {
- mitm[i].base_type = (unsigned char) unmarshallByte(th);
- mitm[i].sub_type = (unsigned char) unmarshallByte(th);
- mitm[i].plus = unmarshallShort(th);
- mitm[i].plus2 = unmarshallShort(th);
- mitm[i].special = unmarshallLong(th);
- mitm[i].quantity = unmarshallShort(th);
- mitm[i].colour = (unsigned char) unmarshallByte(th);
- mitm[i].x = unmarshallShort(th);
- mitm[i].y = unmarshallShort(th);
- mitm[i].flags = (unsigned long) unmarshallLong(th);
-
- // [dshaligram] FIXME, remove this kludge when ARM_CAP is fully
- // integrated.
- if (mitm[i].base_type == OBJ_ARMOUR && mitm[i].sub_type == ARM_CAP)
- mitm[i].sub_type = ARM_HELMET;
-
- unmarshallShort(th); // mitm[].link -- unused
- unmarshallShort(th); // igrd[mitm[i].x][mitm[i].y] -- unused
-
- mitm[i].slot = unmarshallByte(th);
- mitm[i].inscription.clear();
+ unmarshall_item(th, mitm[i]);
+}
- mitm[i].orig_place = unmarshallShort(th);
- mitm[i].orig_monnum = unmarshallShort(th);
-
- char insstring[80];
- unmarshallString(th, insstring, 80);
- mitm[i].inscription = std::string(insstring);
- }
+static void unmarshall_monster(tagHeader &th, monsters &m)
+{
+ m.ac = unmarshallByte(th);
+ m.ev = unmarshallByte(th);
+ m.hit_dice = unmarshallByte(th);
+ m.speed = unmarshallByte(th);
+ // Avoid sign extension when loading files (Elethiomel's hang)
+ m.speed_increment = (unsigned char) unmarshallByte(th);
+ m.behaviour = unmarshallByte(th);
+ m.x = unmarshallByte(th);
+ m.y = unmarshallByte(th);
+ m.target_x = unmarshallByte(th);
+ m.target_y = unmarshallByte(th);
+ m.flags = unmarshallLong(th);
+
+ for (int j = 0; j < NUM_MON_ENCHANTS; j++)
+ m.enchantment[j] = unmarshallByte(th);
+
+ m.type = unmarshallShort(th);
+ m.hit_points = unmarshallShort(th);
+ m.max_hit_points = unmarshallShort(th);
+ m.number = unmarshallShort(th);
+
+ m.colour = unmarshallShort(th);
+
+ for (int j = 0; j < NUM_MONSTER_SLOTS; j++)
+ m.inv[j] = unmarshallShort(th);
+
+ for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
+ m.spells[j] = unmarshallShort(th);
+
+ m.god = (god_type) unmarshallByte(th);
+
+ if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
+ m.set_ghost( unmarshallGhost(th) );
}
static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
{
- int i,j;
+ int i;
int count, ecount, icount;
// how many mons_alloc?
@@ -1502,41 +1616,7 @@ static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
for (i = 0; i < count; i++)
{
monsters &m = menv[i];
-
- m.ac = unmarshallByte(th);
- m.ev = unmarshallByte(th);
- m.hit_dice = unmarshallByte(th);
- m.speed = unmarshallByte(th);
- // Avoid sign extension when loading files (Elethiomel's hang)
- m.speed_increment = (unsigned char) unmarshallByte(th);
- m.behaviour = unmarshallByte(th);
- m.x = unmarshallByte(th);
- m.y = unmarshallByte(th);
- m.target_x = unmarshallByte(th);
- m.target_y = unmarshallByte(th);
- m.flags = unmarshallLong(th);
-
- for (j = 0; j < ecount; j++)
- m.enchantment[j] = unmarshallByte(th);
-
- m.type = unmarshallShort(th);
- m.hit_points = unmarshallShort(th);
- m.max_hit_points = unmarshallShort(th);
- m.number = unmarshallShort(th);
-
- m.colour = unmarshallShort(th);
-
- for (j = 0; j < icount; j++)
- m.inv[j] = unmarshallShort(th);
-
- for (j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)
- m.spells[j] = unmarshallShort(th);
-
- m.god = (god_type) unmarshallByte(th);
-
- if (m.type == MONS_PLAYER_GHOST || m.type == MONS_PANDEMONIUM_DEMON)
- m.set_ghost( unmarshallGhost(th) );
-
+ unmarshall_monster(th, m);
// place monster
if (m.type != -1)
mgrd[m.x][m.y] = i;