diff options
author | pauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-04-09 08:08:51 +0000 |
---|---|---|
committer | pauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-04-09 08:08:51 +0000 |
commit | 9ea95681bd75dd7bbc55a5d96a98e360247028c2 (patch) | |
tree | d7626f601cac746589fd6b06f0dbf28c35a3c810 /crawl-ref/source | |
parent | 26f9ceaeb4fbfe64f099a8f17f61ecc7429d16a1 (diff) | |
download | crawl-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
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/Crawl.xcodeproj/project.pbxproj | 12 | ||||
-rw-r--r-- | crawl-ref/source/makefile.obj | 1 | ||||
-rw-r--r-- | crawl-ref/source/quiver.cc | 296 | ||||
-rw-r--r-- | crawl-ref/source/quiver.h | 47 |
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 |