summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-09 08:08:51 +0000
committerpauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-09 08:08:51 +0000
commit9ea95681bd75dd7bbc55a5d96a98e360247028c2 (patch)
treed7626f601cac746589fd6b06f0dbf28c35a3c810
parent26f9ceaeb4fbfe64f099a8f17f61ecc7429d16a1 (diff)
downloadcrawl-ref-9ea95681bd75dd7bbc55a5d96a98e360247028c2.tar.gz
crawl-ref-9ea95681bd75dd7bbc55a5d96a98e360247028c2.zip
Freshly-rewritten quiver code. This is just a checkpoint, and it's
used from anywhere yet. It should compile. Let me know if it doesn't, or if I've modified the makefiles incorrectly. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4161 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/Crawl.xcodeproj/project.pbxproj12
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/quiver.cc296
-rw-r--r--crawl-ref/source/quiver.h47
4 files changed, 354 insertions, 2 deletions
diff --git a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
index 17b118efcb..a71a95e613 100644
--- a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
+++ b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
@@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */
4CEF158A0C128CA5002C7D7A /* xom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4CEF15890C128CA5002C7D7A /* xom.cc */; };
+ 6232EBE20DACA55C004F7E9C /* quiver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6232EBE00DACA55C004F7E9C /* quiver.cc */; };
+ 6232EBE30DACA55C004F7E9C /* quiver.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 6232EBE10DACA55C004F7E9C /* quiver.h */; };
7B0EFD840BD12EEB00002671 /* lapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFD4C0BD12EEB00002671 /* lapi.c */; };
7B0EFD850BD12EEB00002671 /* lapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B0EFD4D0BD12EEB00002671 /* lapi.h */; settings = {ATTRIBUTES = (); }; };
7B0EFD860BD12EEB00002671 /* lauxlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B0EFD4E0BD12EEB00002671 /* lauxlib.c */; };
@@ -358,6 +360,7 @@
7B6164310C9CA8E80054B3D9 /* state.h in CopyFiles */,
7B6164330C9CA8E80054B3D9 /* terrain.h in CopyFiles */,
7B6164350C9CA8E80054B3D9 /* traps.h in CopyFiles */,
+ 6232EBE30DACA55C004F7E9C /* quiver.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@@ -375,6 +378,8 @@
/* Begin PBXFileReference section */
4CEF15890C128CA5002C7D7A /* xom.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = xom.cc; sourceTree = "<group>"; };
+ 6232EBE00DACA55C004F7E9C /* quiver.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = quiver.cc; sourceTree = "<group>"; };
+ 6232EBE10DACA55C004F7E9C /* quiver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = quiver.h; sourceTree = "<group>"; };
7B0EFD420BD12E9200002671 /* liblua.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = liblua.a; sourceTree = BUILT_PRODUCTS_DIR; };
7B0EFD4C0BD12EEB00002671 /* lapi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = lapi.c; sourceTree = "<group>"; };
7B0EFD4D0BD12EEB00002671 /* lapi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lapi.h; sourceTree = "<group>"; };
@@ -608,11 +613,11 @@
7BF8556A0C9C916800B7C520 /* dgnevent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dgnevent.h; sourceTree = SOURCE_ROOT; };
7BF8556E0C9C919100B7C520 /* luadgn.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = luadgn.cc; sourceTree = SOURCE_ROOT; };
7BF8556F0C9C919100B7C520 /* luadgn.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = luadgn.h; sourceTree = SOURCE_ROOT; };
- 8DD76FB20486AB0100D96B5E /* crawl */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = crawl; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8DD76FB20486AB0100D96B5E /* crawl */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = crawl; sourceTree = BUILT_PRODUCTS_DIR; };
D2A696BC0DA29D4E00FDDE82 /* Crawl.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Crawl.icns; path = mac/Crawl.icns; sourceTree = "<group>"; };
D2AE25EE0DA2624E00E15489 /* crawl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; name = crawl; path = mac/crawl; sourceTree = "<group>"; };
D2F271F60DA1C58C00445FE9 /* Crawl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Crawl.app; sourceTree = BUILT_PRODUCTS_DIR; };
- D2F271F80DA1C58C00445FE9 /* Crawl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Crawl-Info.plist"; sourceTree = "<group>"; };
+ D2F271F80DA1C58C00445FE9 /* Crawl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Crawl-Info.plist"; sourceTree = "<group>"; };
D2F271FE0DA1C5AD00445FE9 /* dat */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dat; sourceTree = "<group>"; };
D2F2723F0DA1C61600445FE9 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = docs; path = ../docs; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -648,6 +653,8 @@
08FB7794FE84155DC02AAC07 /* Crawl */ = {
isa = PBXGroup;
children = (
+ 6232EBE00DACA55C004F7E9C /* quiver.cc */,
+ 6232EBE10DACA55C004F7E9C /* quiver.h */,
08FB7795FE84155DC02AAC07 /* Source */,
7B352F1B0B0022C900CABB32 /* Resources */,
7B3B07610BD13B1700F2980E /* Libraries */,
@@ -1247,6 +1254,7 @@
7B54B51B0CA8217900612805 /* state.cc in Sources */,
7BD222200CC2D51300B475D8 /* store.cc in Sources */,
7B4896620CD3A5D2004A5F43 /* mgrow.cc in Sources */,
+ 6232EBE20DACA55C004F7E9C /* quiver.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index 7db98a3fb2..ae4db2fb9c 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -60,6 +60,7 @@ output.o \
overmap.o \
place.o \
player.o \
+quiver.o \
randart.o \
religion.o \
shopping.o \
diff --git a/crawl-ref/source/quiver.cc b/crawl-ref/source/quiver.cc
new file mode 100644
index 0000000000..07c6cf32dd
--- /dev/null
+++ b/crawl-ref/source/quiver.cc
@@ -0,0 +1,296 @@
+/*
+ * File: quiver.cc
+ * Summary: Player quiver functionality
+ *
+ * Last modified by $Author: $ on $Date: $
+ *
+ * - Only change last_used when actually using
+ * - Not changing Qv; nobody knows about internals
+ * - Track last_used of each type so each weapon can do the right thing
+ */
+
+#include "AppHdr.h"
+#include "quiver.h"
+
+#include "item_use.h"
+#include "itemprop.h"
+#include "items.h"
+#include "stuff.h"
+
+// checks base_type for OBJ_UNASSIGNED, and quantity
+// bool is_valid_item( const item_def &item )
+
+static int _get_pack_slot(const item_def&);
+static ammo_t _get_weapon_ammo_type();
+static bool _item_matches(const item_def &item, fire_type types);
+
+// ----------------------------------------------------------------------
+// player_quiver
+// ----------------------------------------------------------------------
+
+player_quiver::player_quiver()
+ : m_last_used_type(AMMO_INVALID)
+{
+ COMPILE_CHECK(ARRAYSIZE(m_last_used_of_type) == NUM_AMMO, a);
+}
+
+// Return item that we would like to fire by default, and its inv slot
+// (if there are any in inv). If the item is in inv, its count will
+// be correct.
+// This is the item that will be displayed in Qv:
+void player_quiver::get_desired_item(const item_def** item_out, int* slot_out) const
+{
+ if (m_last_used_type == AMMO_INVALID)
+ {
+ *item_out = NULL;
+ *slot_out = -1;
+ }
+ else
+ {
+ *slot_out = _get_pack_slot(m_last_used_of_type[m_last_used_type]);
+ if (*slot_out == -1)
+ {
+ // Not in inv, but caller can at least get the type of the item.
+ *item_out = &m_last_used_of_type[m_last_used_type];
+ }
+ else
+ {
+ // Return the item in inv, since it will have an accurate count
+ *item_out = &you.inv[*slot_out];
+ }
+ }
+}
+
+// Return inv slot of item that should be fired by default.
+// This is the first item displayed in the fire interface.
+int player_quiver::get_default_slot(std::string& no_item_reason) const
+{
+ int slot;
+ const item_def* desired_item;
+
+ get_desired_item(&desired_item, &slot);
+
+ // If not in inv, try the head of the fire order
+ if (slot == -1)
+ {
+ std::vector<int> order;
+ _get_fire_order(order, false);
+ if (order.size())
+ slot = order[0];
+ }
+
+ // If we can't find anything, tell caller why
+ if (slot == -1)
+ {
+ std::vector<int> full_fire_order;
+ _get_fire_order(full_fire_order, true);
+ if (full_fire_order.size() == 0)
+ {
+ no_item_reason = "No suitable missiles.";
+ }
+ else
+ {
+ const int skipped_item = full_fire_order[0];
+ if (skipped_item < Options.fire_items_start)
+ {
+ no_item_reason = make_stringf(
+ "Nothing suitable (fire_items_start = '%c').",
+ index_to_letter(Options.fire_items_start));
+ }
+ else
+ {
+ no_item_reason = make_stringf(
+ "Nothing suitable (ignored '=f'-inscribed item on '%c').",
+ index_to_letter(skipped_item));
+ }
+ }
+ }
+
+ return slot;
+}
+
+// Notification that ltem was fired with 'f'
+void player_quiver::on_item_fired(const item_def& item)
+{
+ // If item matches the launcher, put it in that launcher's last-used item.
+ // Otherwise, it goes into last hand-thrown item.
+
+ const item_def *weapon = you.weapon();
+
+ if (weapon && item.launched_by(*weapon))
+ {
+ const ammo_t t = _get_weapon_ammo_type();
+ m_last_used_of_type[t] = item;
+ m_last_used_of_type[t].quantity = 1; // ensure it's valid
+ }
+ else
+ {
+ m_last_used_of_type[AMMO_THROW] = item;
+ m_last_used_of_type[AMMO_THROW].quantity = 1;
+ }
+}
+
+// Notification that ltem was fired with 'f' 't'
+void player_quiver::on_item_thrown(const item_def& item)
+{
+ m_last_used_of_type[AMMO_THROW] = item;
+ m_last_used_of_type[AMMO_THROW].quantity = 1;
+}
+
+void player_quiver::on_weapon_changed()
+{
+ m_last_used_type = _get_weapon_ammo_type();
+}
+
+void player_quiver::_get_fire_order(std::vector<int>& order, bool ignore_inscription_etc) const
+{
+ const int inv_start = (ignore_inscription_etc ? 0 : Options.fire_items_start);
+
+ // If in a net, cannot throw anything, and can only launch from blowgun
+ if (you.attribute[ATTR_HELD])
+ {
+ const item_def *weapon = you.weapon();
+ if (weapon && weapon->sub_type == WPN_BLOWGUN)
+ for (int i_inv=inv_start; i_inv<ENDOFPACK; i_inv++)
+ if (is_valid_item(you.inv[i_inv]) && you.inv[i_inv].launched_by(*weapon))
+ order.push_back(i_inv);
+ return;
+ }
+
+ for (int i_inv=inv_start; i_inv<ENDOFPACK; i_inv++)
+ {
+ const item_def& item = you.inv[i_inv];
+ if (!is_valid_item(item))
+ continue;
+ if (you.equip[EQ_WEAPON] == i_inv)
+ continue;
+
+ // =f prevents item from being in fire order
+ if (!ignore_inscription_etc &&
+ strstr(item.inscription.c_str(), "=f"))
+ {
+ continue;
+ }
+
+ for (unsigned int i_flags=0;
+ i_flags<Options.fire_order.size();
+ i_flags++)
+ {
+ if (_item_matches(item, (fire_type)Options.fire_order[i_flags]))
+ {
+ order.push_back( (i_flags<<16) | (i_inv & 0xffff) );
+ break;
+ }
+ }
+ }
+
+ std::sort(order.begin(), order.end());
+
+ for (unsigned int i=0; i<order.size(); i++)
+ {
+ order[i] &= 0xffff;
+ }
+}
+
+// ----------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------
+
+// Helper for _get_fire_order
+// types may actually contain more than one fire_type
+static bool _item_matches(const item_def &item, fire_type types)
+{
+ ASSERT(!is_valid_item(item));
+
+ if (types & FIRE_INSCRIBED)
+ if (item.inscription.find("+f", 0) != std::string::npos)
+ return true;
+
+ if (item.base_type == OBJ_MISSILES)
+ {
+ if ((types & FIRE_DART) && item.sub_type == MI_DART)
+ return (true);
+ if ((types & FIRE_STONE) && item.sub_type == MI_STONE)
+ return (true);
+ if ((types & FIRE_JAVELIN) && item.sub_type == MI_JAVELIN)
+ return (true);
+ if ((types & FIRE_ROCK) && item.sub_type == MI_LARGE_ROCK)
+ return (true);
+ if ((types & FIRE_NET) && item.sub_type == MI_THROWING_NET)
+ return (true);
+
+ if (types & FIRE_LAUNCHER)
+ {
+ const item_def *weapon = you.weapon();
+ if (weapon && item.launched_by(*weapon))
+ return (true);
+ }
+ }
+ else if (item.base_type == OBJ_WEAPONS
+ && is_throwable(item, you.body_size()))
+ {
+ if ( (types & FIRE_RETURNING)
+ && item.special == SPWPN_RETURNING
+ && item_ident(item, ISFLAG_KNOW_TYPE))
+ {
+ return (true);
+ }
+ if ((types & FIRE_DAGGER) && item.sub_type == WPN_DAGGER)
+ return (true);
+ if ((types & FIRE_SPEAR) && item.sub_type == WPN_SPEAR)
+ return (true);
+ if ((types & FIRE_HAND_AXE) && item.sub_type == WPN_HAND_AXE)
+ return (true);
+ if ((types & FIRE_CLUB) && item.sub_type == WPN_CLUB)
+ return (true);
+ }
+ return (false);
+}
+
+// Return inv slot that contains an item that looks like item,
+// or -1 if not in inv.
+static int _get_pack_slot(const item_def& item)
+{
+ if (! is_valid_item(item))
+ return -1;
+
+ for (int i=0; i<ENDOFPACK; i++)
+ {
+ if (items_stack(item, you.inv[i]))
+ return i;
+ }
+
+ return -1;
+}
+
+
+// Return the type of ammo used by the player's equipped weapon,
+// or AMMO_THROW if it's not a launcher.
+static ammo_t _get_weapon_ammo_type()
+{
+ const int wielded = you.equip[EQ_WEAPON];
+ if (wielded == -1)
+ return (AMMO_THROW);
+
+ item_def &weapon = you.inv[wielded];
+
+ if (weapon.base_type != OBJ_WEAPONS)
+ return (AMMO_THROW);
+
+ switch (weapon.sub_type)
+ {
+ case WPN_BLOWGUN:
+ return (AMMO_BLOWGUN);
+ case WPN_SLING:
+ return (AMMO_SLING);
+ case WPN_BOW:
+ case WPN_LONGBOW:
+ return (AMMO_BOW);
+ case WPN_CROSSBOW:
+ return (AMMO_CROSSBOW);
+ case WPN_HAND_CROSSBOW:
+ return (AMMO_HAND_CROSSBOW);
+ default:
+ return (AMMO_THROW);
+ }
+}
diff --git a/crawl-ref/source/quiver.h b/crawl-ref/source/quiver.h
new file mode 100644
index 0000000000..aee70e74fe
--- /dev/null
+++ b/crawl-ref/source/quiver.h
@@ -0,0 +1,47 @@
+/*
+ * File: quiver.h
+ * Summary: Player quiver functionality
+ *
+ * Last modified by $Author: $ on $Date: $
+ */
+
+#ifndef QUIVER_H
+#define QUIVER_H
+
+#include "externs.h" /* item_def */
+#include <vector>
+
+enum ammo_t
+{
+ AMMO_THROW, // no launcher wielded -> darts, stones, ...
+ AMMO_BOW, // wielded bow -> arrows
+ AMMO_SLING, // wielded sling -> stones, sling bullets
+ AMMO_CROSSBOW, // wielded crossbow -> bolts
+ AMMO_HAND_CROSSBOW, // wielded hand crossbow -> darts
+ AMMO_BLOWGUN, // wielded blowgun -> needles
+ NUM_AMMO,
+ AMMO_INVALID=-1
+};
+
+class player_quiver
+{
+ public:
+ player_quiver();
+
+ void get_desired_item(const item_def** item_out, int* slot_out) const;
+ // Returns an item, or a reason why we returned an invalid item
+ int get_default_slot(std::string& no_item_reason) const;
+ void get_fire_order(std::vector<int>& v) const { _get_fire_order(v, false); }
+
+ void on_item_fired(const item_def&);
+ void on_item_thrown(const item_def&);
+ void on_weapon_changed();
+
+ private:
+ void _get_fire_order(std::vector<int>&, bool ignore_inscription_etc) const;
+ private:
+ ammo_t m_last_used_type;
+ item_def m_last_used_of_type[NUM_AMMO];
+};
+
+#endif