mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-17 18:36:43 +02:00
#11 ammo counter
This commit is contained in:
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
#define MAX_LAYERS 4
|
#define MAX_LAYERS 4
|
||||||
|
|
||||||
|
#define UNLIMITED_AMMO 10000
|
||||||
|
|
||||||
struct Controller;
|
struct Controller;
|
||||||
|
|
||||||
struct IGame {
|
struct IGame {
|
||||||
@@ -33,6 +35,7 @@ struct IGame {
|
|||||||
|
|
||||||
virtual bool invUse(TR::Entity::Type item, TR::Entity::Type slot) { return false; }
|
virtual bool invUse(TR::Entity::Type item, TR::Entity::Type slot) { return false; }
|
||||||
virtual void invAdd(TR::Entity::Type type, int count = 1) {}
|
virtual void invAdd(TR::Entity::Type type, int count = 1) {}
|
||||||
|
virtual int* invCount(TR::Entity::Type type) { return NULL; }
|
||||||
|
|
||||||
virtual Sound::Sample* playSound(int id, const vec3 &pos, int flags, int group = -1) const { return NULL; }
|
virtual Sound::Sample* playSound(int id, const vec3 &pos, int flags, int group = -1) const { return NULL; }
|
||||||
};
|
};
|
||||||
|
10
src/format.h
10
src/format.h
@@ -93,10 +93,10 @@
|
|||||||
E( INV_PASSPORT_CLOSED ) \
|
E( INV_PASSPORT_CLOSED ) \
|
||||||
E( INV_MAP ) \
|
E( INV_MAP ) \
|
||||||
E( CRYSTAL ) \
|
E( CRYSTAL ) \
|
||||||
E( WEAPON_PISTOLS ) \
|
E( PISTOLS ) \
|
||||||
E( WEAPON_SHOTGUN ) \
|
E( SHOTGUN ) \
|
||||||
E( WEAPON_MAGNUMS ) \
|
E( MAGNUMS ) \
|
||||||
E( WEAPON_UZIS ) \
|
E( UZIS ) \
|
||||||
E( AMMO_PISTOLS ) \
|
E( AMMO_PISTOLS ) \
|
||||||
E( AMMO_SHOTGUN ) \
|
E( AMMO_SHOTGUN ) \
|
||||||
E( AMMO_MAGNUMS ) \
|
E( AMMO_MAGNUMS ) \
|
||||||
@@ -631,7 +631,7 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int isItem() {
|
int isItem() {
|
||||||
return (type >= WEAPON_PISTOLS && type <= AMMO_UZIS) ||
|
return (type >= PISTOLS && type <= AMMO_UZIS) ||
|
||||||
(type >= PUZZLE_1 && type <= PUZZLE_4) ||
|
(type >= PUZZLE_1 && type <= PUZZLE_4) ||
|
||||||
(type >= KEY_1 && type <= KEY_4) ||
|
(type >= KEY_1 && type <= KEY_4) ||
|
||||||
(type == MEDIKIT_SMALL || type == MEDIKIT_BIG || type == SCION_1); // TODO: recheck all items
|
(type == MEDIKIT_SMALL || type == MEDIKIT_BIG || type == SCION_1); // TODO: recheck all items
|
||||||
|
154
src/inventory.h
154
src/inventory.h
@@ -129,7 +129,7 @@ struct Inventory {
|
|||||||
if (anim) anim->setAnim(0, 0, false);
|
if (anim) anim->setAnim(0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} items[INVENTORY_MAX_ITEMS];
|
} *items[INVENTORY_MAX_ITEMS];
|
||||||
|
|
||||||
Inventory(IGame *game) : game(game), active(false), chosen(false), index(0), targetIndex(0), page(PAGE_OPTION), targetPage(PAGE_OPTION), itemsCount(0) {
|
Inventory(IGame *game) : game(game), active(false), chosen(false), index(0), targetIndex(0), page(PAGE_OPTION), targetPage(PAGE_OPTION), itemsCount(0) {
|
||||||
TR::Level *level = game->getLevel();
|
TR::Level *level = game->getLevel();
|
||||||
@@ -145,16 +145,16 @@ struct Inventory {
|
|||||||
if (level->extra.inv.gamma != -1)
|
if (level->extra.inv.gamma != -1)
|
||||||
add(TR::Entity::INV_GAMMA);
|
add(TR::Entity::INV_GAMMA);
|
||||||
|
|
||||||
add(TR::Entity::INV_PISTOLS, 999);
|
add(TR::Entity::INV_PISTOLS, UNLIMITED_AMMO);
|
||||||
add(TR::Entity::INV_SHOTGUN, 999);
|
add(TR::Entity::INV_SHOTGUN, 999);
|
||||||
add(TR::Entity::INV_MAGNUMS, 999);
|
add(TR::Entity::INV_MAGNUMS, 999);
|
||||||
add(TR::Entity::INV_UZIS, 999);
|
add(TR::Entity::INV_UZIS, 10);
|
||||||
add(TR::Entity::INV_MEDIKIT_SMALL, 999);
|
// add(TR::Entity::INV_MEDIKIT_SMALL, 999);
|
||||||
add(TR::Entity::INV_MEDIKIT_BIG, 999);
|
// add(TR::Entity::INV_MEDIKIT_BIG, 999);
|
||||||
|
|
||||||
add(TR::Entity::INV_SCION, 1);
|
// add(TR::Entity::INV_SCION, 1);
|
||||||
add(TR::Entity::INV_KEY_1, 1);
|
// add(TR::Entity::INV_KEY_1, 1);
|
||||||
add(TR::Entity::INV_PUZZLE_1, 1);
|
// add(TR::Entity::INV_PUZZLE_1, 1);
|
||||||
|
|
||||||
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
||||||
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
||||||
@@ -164,6 +164,9 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~Inventory() {
|
~Inventory() {
|
||||||
|
for (int i = 0; i < itemsCount; i++)
|
||||||
|
delete items[i];
|
||||||
|
|
||||||
for (int i = 0; i < COUNT(background); i++)
|
for (int i = 0; i < COUNT(background); i++)
|
||||||
delete background[i];
|
delete background[i];
|
||||||
}
|
}
|
||||||
@@ -172,9 +175,41 @@ struct Inventory {
|
|||||||
return active || phaseRing > 0.0f;
|
return active || phaseRing > 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TR::Entity::Type convToInv(TR::Entity::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case TR::Entity::PISTOLS : return TR::Entity::INV_PISTOLS;
|
||||||
|
case TR::Entity::SHOTGUN : return TR::Entity::INV_SHOTGUN;
|
||||||
|
case TR::Entity::MAGNUMS : return TR::Entity::INV_MAGNUMS;
|
||||||
|
case TR::Entity::UZIS : return TR::Entity::INV_UZIS;
|
||||||
|
|
||||||
|
case TR::Entity::AMMO_PISTOLS : return TR::Entity::INV_AMMO_PISTOLS;
|
||||||
|
case TR::Entity::AMMO_SHOTGUN : return TR::Entity::INV_AMMO_SHOTGUN;
|
||||||
|
case TR::Entity::AMMO_MAGNUMS : return TR::Entity::INV_AMMO_MAGNUMS;
|
||||||
|
case TR::Entity::AMMO_UZIS : return TR::Entity::INV_AMMO_UZIS;
|
||||||
|
|
||||||
|
case TR::Entity::MEDIKIT_SMALL : return TR::Entity::INV_MEDIKIT_SMALL;
|
||||||
|
case TR::Entity::MEDIKIT_BIG : return TR::Entity::INV_MEDIKIT_BIG;
|
||||||
|
|
||||||
|
case TR::Entity::PUZZLE_1 : return TR::Entity::INV_PUZZLE_1;
|
||||||
|
case TR::Entity::PUZZLE_2 : return TR::Entity::INV_PUZZLE_2;
|
||||||
|
case TR::Entity::PUZZLE_3 : return TR::Entity::INV_PUZZLE_3;
|
||||||
|
case TR::Entity::PUZZLE_4 : return TR::Entity::INV_PUZZLE_4;
|
||||||
|
|
||||||
|
case TR::Entity::KEY_1 : return TR::Entity::INV_KEY_1;
|
||||||
|
case TR::Entity::KEY_2 : return TR::Entity::INV_KEY_2;
|
||||||
|
case TR::Entity::KEY_3 : return TR::Entity::INV_KEY_3;
|
||||||
|
case TR::Entity::KEY_4 : return TR::Entity::INV_KEY_4;
|
||||||
|
|
||||||
|
case TR::Entity::LEADBAR : return TR::Entity::INV_LEADBAR;
|
||||||
|
//case TR::Entity::SCION : return TR::Entity::INV_SCION;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
int contains(TR::Entity::Type type) {
|
int contains(TR::Entity::Type type) {
|
||||||
|
type = convToInv(type);
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemsCount; i++)
|
||||||
if (items[i].type == type)
|
if (items[i]->type == type)
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -182,15 +217,17 @@ struct Inventory {
|
|||||||
void add(TR::Entity::Type type, int count = 1) {
|
void add(TR::Entity::Type type, int count = 1) {
|
||||||
int i = contains(type);
|
int i = contains(type);
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
items[i].count += count;
|
items[i]->count += count;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(itemsCount < INVENTORY_MAX_ITEMS);
|
ASSERT(itemsCount < INVENTORY_MAX_ITEMS);
|
||||||
|
|
||||||
|
type = convToInv(type);
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (int pos = 0; pos < itemsCount; pos++)
|
for (int pos = 0; pos < itemsCount; pos++)
|
||||||
if (items[pos].type > type)
|
if (items[pos]->type > type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pos - itemsCount) {
|
if (pos - itemsCount) {
|
||||||
@@ -198,36 +235,52 @@ struct Inventory {
|
|||||||
items[i] = items[i - 1];
|
items[i] = items[i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Item it(game->getLevel(), type, count);
|
items[pos] = new Item(game->getLevel(), type, count);
|
||||||
items[pos] = it;
|
|
||||||
itemsCount++;
|
itemsCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getCount(TR::Entity::Type type) {
|
int* getCountPtr(TR::Entity::Type type) {
|
||||||
int i = contains(type);
|
int i = contains(type);
|
||||||
if (i < 0) return 0;
|
if (i < 0) return NULL;
|
||||||
return items[i].count;
|
return &items[i]->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(TR::Entity::Type type, int count = 1) {
|
void remove(TR::Entity::Type type, int count = 1) {
|
||||||
int i = contains(type);
|
int idx = contains(type);
|
||||||
if (i > -1)
|
if (idx > -1) {
|
||||||
items[i].count -= count;
|
items[idx]->count -= count;
|
||||||
|
if (!items[idx]->count) {
|
||||||
|
delete items[idx];
|
||||||
|
for (int i = idx; i < itemsCount - 1; i++) {
|
||||||
|
items[i] = items[i + 1];
|
||||||
|
}
|
||||||
|
itemsCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use(TR::Entity::Type item, TR::Entity::Type slot) {
|
bool use(TR::Entity::Type item, TR::Entity::Type slot) {
|
||||||
if (item == TR::Entity::NONE) {
|
|
||||||
switch (slot) {
|
switch (slot) {
|
||||||
case TR::Entity::KEY_HOLE_1 : item = TR::Entity::KEY_1; break; // TODO: 1-4
|
case TR::Entity::PUZZLE_HOLE_1 : item = TR::Entity::INV_PUZZLE_1; break;
|
||||||
case TR::Entity::PUZZLE_HOLE_1 : item = TR::Entity::PUZZLE_1; break;
|
case TR::Entity::PUZZLE_HOLE_2 : item = TR::Entity::INV_PUZZLE_2; break;
|
||||||
|
case TR::Entity::PUZZLE_HOLE_3 : item = TR::Entity::INV_PUZZLE_3; break;
|
||||||
|
case TR::Entity::PUZZLE_HOLE_4 : item = TR::Entity::INV_PUZZLE_4; break;
|
||||||
|
case TR::Entity::KEY_HOLE_1 : item = TR::Entity::INV_KEY_1; break;
|
||||||
|
case TR::Entity::KEY_HOLE_2 : item = TR::Entity::INV_KEY_2; break;
|
||||||
|
case TR::Entity::KEY_HOLE_3 : item = TR::Entity::INV_KEY_3; break;
|
||||||
|
case TR::Entity::KEY_HOLE_4 : item = TR::Entity::INV_KEY_4; break;
|
||||||
|
case TR::Entity::INV_PISTOLS :
|
||||||
|
case TR::Entity::INV_SHOTGUN :
|
||||||
|
case TR::Entity::INV_MAGNUMS :
|
||||||
|
case TR::Entity::INV_UZIS : return false;
|
||||||
default : return false;
|
default : return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (getCount(item) > 0) {
|
if (getCountPtr(item)) {
|
||||||
remove(item);
|
remove(item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +293,7 @@ struct Inventory {
|
|||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemsCount; i++)
|
||||||
items[i].reset();
|
items[i]->reset();
|
||||||
|
|
||||||
phasePage = 1.0f;
|
phasePage = 1.0f;
|
||||||
phaseSelect = 1.0f;
|
phaseSelect = 1.0f;
|
||||||
@@ -269,7 +322,7 @@ struct Inventory {
|
|||||||
|
|
||||||
int getItemIndex(Page page, int index) {
|
int getItemIndex(Page page, int index) {
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemsCount; i++)
|
||||||
if (items[i].desc.page == page) {
|
if (items[i]->desc.page == page) {
|
||||||
if (!index)
|
if (!index)
|
||||||
return i;
|
return i;
|
||||||
index--;
|
index--;
|
||||||
@@ -285,7 +338,7 @@ struct Inventory {
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < itemsCount; i++)
|
for (int i = 0; i < itemsCount; i++)
|
||||||
if (items[i].desc.page == page)
|
if (items[i]->desc.page == page)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
@@ -293,7 +346,7 @@ struct Inventory {
|
|||||||
|
|
||||||
bool showHealthBar() {
|
bool showHealthBar() {
|
||||||
int idx = getItemIndex(page, index);
|
int idx = getItemIndex(page, index);
|
||||||
TR::Entity::Type type = items[idx].type;
|
TR::Entity::Type type = items[idx]->type;
|
||||||
return active && phaseRing == 1.0f && index == targetIndex && phasePage == 1.0f && (type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG);
|
return active && phaseRing == 1.0f && index == targetIndex && phasePage == 1.0f && (type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,15 +382,15 @@ struct Inventory {
|
|||||||
|
|
||||||
vec3 p;
|
vec3 p;
|
||||||
|
|
||||||
Item &item = items[getItemIndex(page, index)];
|
Item *item = items[getItemIndex(page, index)];
|
||||||
|
|
||||||
if (index == targetIndex && ready) {
|
if (index == targetIndex && ready) {
|
||||||
if (Input::state[cAction] && (phaseChoose == 0.0f || (phaseChoose == 1.0f && item.anim->isEnded))) {
|
if (Input::state[cAction] && (phaseChoose == 0.0f || (phaseChoose == 1.0f && item->anim->isEnded))) {
|
||||||
chosen = !chosen;
|
chosen = !chosen;
|
||||||
if (!chosen) {
|
if (!chosen) {
|
||||||
item.angle = 0.0f;
|
item->angle = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
switch (item.type) {
|
switch (item->type) {
|
||||||
case TR::Entity::INV_COMPASS : game->playSound(TR::SND_INV_COMPASS, p, 0, 0); break;
|
case TR::Entity::INV_COMPASS : game->playSound(TR::SND_INV_COMPASS, p, 0, 0); break;
|
||||||
case TR::Entity::INV_HOME : game->playSound(TR::SND_INV_HOME, p, 0, 0); break;
|
case TR::Entity::INV_HOME : game->playSound(TR::SND_INV_HOME, p, 0, 0); break;
|
||||||
case TR::Entity::INV_CONTROLS : game->playSound(TR::SND_INV_CONTROLS, p, 0, 0); break;
|
case TR::Entity::INV_CONTROLS : game->playSound(TR::SND_INV_CONTROLS, p, 0, 0); break;
|
||||||
@@ -347,7 +400,7 @@ struct Inventory {
|
|||||||
case TR::Entity::INV_UZIS : game->playSound(TR::SND_INV_WEAPON, p, 0, 0); break;
|
case TR::Entity::INV_UZIS : game->playSound(TR::SND_INV_WEAPON, p, 0, 0); break;
|
||||||
default : game->playSound(TR::SND_INV_SHOW, p, 0, 0); break;
|
default : game->playSound(TR::SND_INV_SHOW, p, 0, 0); break;
|
||||||
}
|
}
|
||||||
item.choose();
|
item->choose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,8 +410,8 @@ struct Inventory {
|
|||||||
int itemIndex = index == targetIndex ? getItemIndex(page, index) : -1;
|
int itemIndex = index == targetIndex ? getItemIndex(page, index) : -1;
|
||||||
|
|
||||||
for (int i = 0; i < itemsCount; i++) {
|
for (int i = 0; i < itemsCount; i++) {
|
||||||
items[i].update();
|
items[i]->update();
|
||||||
float &angle = items[i].angle;
|
float &angle = items[i]->angle;
|
||||||
|
|
||||||
if (itemIndex != i || chosen) {
|
if (itemIndex != i || chosen) {
|
||||||
if (angle == 0.0f) {
|
if (angle == 0.0f) {
|
||||||
@@ -378,8 +431,8 @@ struct Inventory {
|
|||||||
angle = clampAngle(angle);
|
angle = clampAngle(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ready && chosen && phaseChoose == 1.0f && item.anim->isEnded) {
|
if (ready && chosen && phaseChoose == 1.0f && item->anim->isEnded) {
|
||||||
TR::Entity::Type type = item.type;
|
TR::Entity::Type type = item->type;
|
||||||
|
|
||||||
if (type == TR::Entity::INV_PISTOLS || type == TR::Entity::INV_SHOTGUN || type == TR::Entity::INV_MAGNUMS || type == TR::Entity::INV_UZIS ||
|
if (type == TR::Entity::INV_PISTOLS || type == TR::Entity::INV_SHOTGUN || type == TR::Entity::INV_MAGNUMS || type == TR::Entity::INV_UZIS ||
|
||||||
type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG) {
|
type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG) {
|
||||||
@@ -420,26 +473,29 @@ struct Inventory {
|
|||||||
Core::setDepthTest(true);
|
Core::setDepthTest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderItemText(const Item &item, float width) {
|
void renderItemCount(const Item *item, const vec2 &pos, float width) {
|
||||||
UI::textOut(game, vec2(0, 480 - 16), item.desc.name, UI::aCenter, width);
|
|
||||||
|
|
||||||
if (item.count > 1) {
|
|
||||||
char spec;
|
char spec;
|
||||||
switch (item.type) {
|
switch (item->type) {
|
||||||
case TR::Entity::INV_SHOTGUN : spec = 12; break;
|
case TR::Entity::INV_SHOTGUN : spec = 12; break;
|
||||||
case TR::Entity::INV_MAGNUMS : spec = 13; break;
|
case TR::Entity::INV_MAGNUMS : spec = 13; break;
|
||||||
case TR::Entity::INV_UZIS : spec = 14; break;
|
case TR::Entity::INV_UZIS : spec = 14; break;
|
||||||
default : spec = 0;
|
default : spec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((item->count > 1 || spec) && item->count < UNLIMITED_AMMO) {
|
||||||
char buf[16];
|
char buf[16];
|
||||||
sprintf(buf, "%d %c", item.count, spec);
|
sprintf(buf, "%d %c", item->count, spec);
|
||||||
for (int i = 0; buf[i] != ' '; i++)
|
for (int i = 0; buf[i] != ' '; i++)
|
||||||
buf[i] -= 47;
|
buf[i] -= 47;
|
||||||
UI::textOut(game, vec2(width / 2 - 160, 480 - 96), buf, UI::aRight, 320);
|
UI::textOut(game, pos, buf, UI::aRight, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderItemText(const Item *item, float width) {
|
||||||
|
UI::textOut(game, vec2(0, 480 - 16), item->desc.name, UI::aCenter, width);
|
||||||
|
renderItemCount(item, vec2(width / 2 - 160, 480 - 96), 320);
|
||||||
|
}
|
||||||
|
|
||||||
void renderPage(int page) {
|
void renderPage(int page) {
|
||||||
float phase = page == targetPage ? phasePage : (1.0f - phasePage);
|
float phase = page == targetPage ? phasePage : (1.0f - phasePage);
|
||||||
|
|
||||||
@@ -462,13 +518,13 @@ struct Inventory {
|
|||||||
|
|
||||||
int itemIndex = 0;
|
int itemIndex = 0;
|
||||||
for (int i = 0; i < itemsCount; i++) {
|
for (int i = 0; i < itemsCount; i++) {
|
||||||
Item &item = items[i];
|
Item *item = items[i];
|
||||||
|
|
||||||
if (item.desc.page != page)
|
if (item->desc.page != page)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float a = getAngle(itemIndex, count) - angle - collapseAngle;
|
float a = getAngle(itemIndex, count) - angle - collapseAngle;
|
||||||
float ia = item.angle;
|
float ia = item->angle;
|
||||||
float ra = ringTilt;
|
float ra = ringTilt;
|
||||||
float rd = radius;
|
float rd = radius;
|
||||||
float rh = ringHeight;
|
float rh = ringHeight;
|
||||||
@@ -480,9 +536,9 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Basis basis = Basis(quat(vec3(1, 0, 0), ra), vec3(0.0f));
|
Basis basis = Basis(quat(vec3(1, 0, 0), ra), vec3(0.0f));
|
||||||
basis = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item.desc.page * INVENTORY_HEIGHT - rh, 0));
|
basis = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item->desc.page * INVENTORY_HEIGHT - rh, 0));
|
||||||
|
|
||||||
item.render(game, basis);
|
item->render(game, basis);
|
||||||
|
|
||||||
itemIndex++;
|
itemIndex++;
|
||||||
}
|
}
|
||||||
|
58
src/lara.h
58
src/lara.h
@@ -197,13 +197,12 @@ struct Lara : Character {
|
|||||||
enum Type { EMPTY = -1, PISTOLS, SHOTGUN, MAGNUMS, UZIS, MAX };
|
enum Type { EMPTY = -1, PISTOLS, SHOTGUN, MAGNUMS, UZIS, MAX };
|
||||||
enum State { IS_HIDDEN, IS_ARMED, IS_FIRING };
|
enum State { IS_HIDDEN, IS_ARMED, IS_FIRING };
|
||||||
enum Anim { NONE, PREPARE, UNHOLSTER, HOLSTER, HOLD, AIM, FIRE };
|
enum Anim { NONE, PREPARE, UNHOLSTER, HOLSTER, HOLD, AIM, FIRE };
|
||||||
|
};
|
||||||
int ammo; // if -1 weapon is not available
|
|
||||||
} weapons[Weapon::MAX];
|
|
||||||
|
|
||||||
Weapon::Type wpnCurrent;
|
Weapon::Type wpnCurrent;
|
||||||
Weapon::Type wpnNext;
|
Weapon::Type wpnNext;
|
||||||
Weapon::State wpnState;
|
Weapon::State wpnState;
|
||||||
|
int *wpnAmmo;
|
||||||
vec3 chestOffset;
|
vec3 chestOffset;
|
||||||
|
|
||||||
struct Arm {
|
struct Arm {
|
||||||
@@ -406,18 +405,9 @@ struct Lara : Character {
|
|||||||
getEntity().flags.active = 1;
|
getEntity().flags.active = 1;
|
||||||
initMeshOverrides();
|
initMeshOverrides();
|
||||||
|
|
||||||
weapons[Weapon::PISTOLS].ammo = -1;
|
if (!home)
|
||||||
weapons[Weapon::SHOTGUN].ammo = -1;
|
|
||||||
weapons[Weapon::MAGNUMS].ammo = -1;
|
|
||||||
weapons[Weapon::UZIS ].ammo = -1;
|
|
||||||
|
|
||||||
if (!home) {
|
|
||||||
weapons[Weapon::PISTOLS].ammo = 0;
|
|
||||||
weapons[Weapon::SHOTGUN].ammo = 9000;
|
|
||||||
weapons[Weapon::MAGNUMS].ammo = 9000;
|
|
||||||
weapons[Weapon::UZIS ].ammo = 9000;
|
|
||||||
wpnSet(Weapon::PISTOLS);
|
wpnSet(Weapon::PISTOLS);
|
||||||
} else
|
else
|
||||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
@@ -433,12 +423,12 @@ struct Lara : Character {
|
|||||||
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
||||||
|
|
||||||
//reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge)
|
//reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge)
|
||||||
reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||||
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
||||||
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
||||||
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
||||||
//reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block)
|
//reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block)
|
||||||
//reset(1, vec3(62630, -1280, 19633), 0); // level 2 (dark medikit)
|
reset(1, vec3(62630, -1280, 19633), 0); // level 2 (dark medikit)
|
||||||
//reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger)
|
//reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger)
|
||||||
//reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
|
//reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
|
||||||
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
|
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
|
||||||
@@ -498,10 +488,24 @@ struct Lara : Character {
|
|||||||
updateLights(false);
|
updateLights(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TR::Entity::Type getCurrentWeaponInv() {
|
||||||
|
switch (wpnCurrent) {
|
||||||
|
case Weapon::Type::PISTOLS : return TR::Entity::PISTOLS;
|
||||||
|
case Weapon::Type::SHOTGUN : return TR::Entity::SHOTGUN;
|
||||||
|
case Weapon::Type::MAGNUMS : return TR::Entity::MAGNUMS;
|
||||||
|
case Weapon::Type::UZIS : return TR::Entity::UZIS;
|
||||||
|
default : return TR::Entity::NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void wpnSet(Weapon::Type wType) {
|
void wpnSet(Weapon::Type wType) {
|
||||||
wpnCurrent = wType;
|
wpnCurrent = wType;
|
||||||
wpnState = Weapon::IS_FIRING;
|
wpnState = Weapon::IS_FIRING;
|
||||||
|
|
||||||
|
TR::Entity::Type invType = getCurrentWeaponInv();
|
||||||
|
|
||||||
|
wpnAmmo = game->invCount(invType);
|
||||||
|
|
||||||
arms[0].animation = arms[1].animation = Animation(level, &level->models[wType == Weapon::SHOTGUN ? TR::MODEL_SHOTGUN : TR::MODEL_PISTOLS]);
|
arms[0].animation = arms[1].animation = Animation(level, &level->models[wType == Weapon::SHOTGUN ? TR::MODEL_SHOTGUN : TR::MODEL_PISTOLS]);
|
||||||
|
|
||||||
wpnSetAnim(arms[0], Weapon::IS_HIDDEN, Weapon::Anim::NONE, 0.0f, 0.0f);
|
wpnSetAnim(arms[0], Weapon::IS_HIDDEN, Weapon::Anim::NONE, 0.0f, 0.0f);
|
||||||
@@ -576,7 +580,7 @@ struct Lara : Character {
|
|||||||
if (wpnCurrent != Weapon::SHOTGUN) {
|
if (wpnCurrent != Weapon::SHOTGUN) {
|
||||||
meshSwap(1, level->extra.weapons[wpnCurrent], mask);
|
meshSwap(1, level->extra.weapons[wpnCurrent], mask);
|
||||||
// have a shotgun in inventory place it on the back if another weapon is in use
|
// have a shotgun in inventory place it on the back if another weapon is in use
|
||||||
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], (weapons[Weapon::SHOTGUN].ammo != -1) ? BODY_CHEST : 0);
|
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], game->invCount(TR::Entity::INV_SHOTGUN) ? BODY_CHEST : 0);
|
||||||
} else {
|
} else {
|
||||||
meshSwap(2, level->extra.weapons[wpnCurrent], mask);
|
meshSwap(2, level->extra.weapons[wpnCurrent], mask);
|
||||||
}
|
}
|
||||||
@@ -755,7 +759,7 @@ struct Lara : Character {
|
|||||||
|
|
||||||
float nearDist = 32.0f * 1024.0f;
|
float nearDist = 32.0f * 1024.0f;
|
||||||
vec3 nearPos;
|
vec3 nearPos;
|
||||||
bool hasShot = false;
|
int shots = 0;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int armIndex;
|
int armIndex;
|
||||||
@@ -768,8 +772,15 @@ struct Lara : Character {
|
|||||||
}
|
}
|
||||||
Arm *arm = &arms[armIndex];
|
Arm *arm = &arms[armIndex];
|
||||||
|
|
||||||
|
if (wpnAmmo && *wpnAmmo != UNLIMITED_AMMO) {
|
||||||
|
if (*wpnAmmo <= 0)
|
||||||
|
continue;
|
||||||
|
if (wpnCurrent != Weapon::SHOTGUN)
|
||||||
|
*wpnAmmo -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
arm->shotTimer = 0.0f;
|
arm->shotTimer = 0.0f;
|
||||||
hasShot = true;
|
shots++;
|
||||||
|
|
||||||
int joint = wpnCurrent == Weapon::SHOTGUN ? 8 : (i ? 11 : 8);
|
int joint = wpnCurrent == Weapon::SHOTGUN ? 8 : (i ? 11 : 8);
|
||||||
|
|
||||||
@@ -798,9 +809,16 @@ struct Lara : Character {
|
|||||||
Core::lightColor[1 + armIndex] = FLASH_LIGHT_COLOR;
|
Core::lightColor[1 + armIndex] = FLASH_LIGHT_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasShot) {
|
if (shots) {
|
||||||
playSound(wpnGetSound(), pos, Sound::Flags::PAN);
|
playSound(wpnGetSound(), pos, Sound::Flags::PAN);
|
||||||
playSound(TR::SND_RICOCHET, nearPos, Sound::Flags::PAN);
|
playSound(TR::SND_RICOCHET, nearPos, Sound::Flags::PAN);
|
||||||
|
|
||||||
|
if (wpnAmmo && *wpnAmmo != UNLIMITED_AMMO && wpnCurrent == Weapon::SHOTGUN)
|
||||||
|
*wpnAmmo -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wpnAmmo && *wpnAmmo != UNLIMITED_AMMO && *wpnAmmo <= 0) {
|
||||||
|
wpnChange(Weapon::PISTOLS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
src/level.h
17
src/level.h
@@ -136,6 +136,10 @@ struct Level : IGame {
|
|||||||
inventory.add(type, count);
|
inventory.add(type, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int* invCount(TR::Entity::Type type) {
|
||||||
|
return inventory.getCountPtr(type);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Sound::Sample* playSound(int id, const vec3 &pos, int flags, int group = -1) const {
|
virtual Sound::Sample* playSound(int id, const vec3 &pos, int flags, int group = -1) const {
|
||||||
if (level.version == TR::Level::VER_TR1_PSX && id == TR::SND_SECRET)
|
if (level.version == TR::Level::VER_TR1_PSX && id == TR::SND_SECRET)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -979,11 +983,18 @@ struct Level : IGame {
|
|||||||
if (oxygen <= 0.2f) oxygen = 0.0f;
|
if (oxygen <= 0.2f) oxygen = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f)))
|
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f))) {
|
||||||
UI::renderBar(0, vec2(32, 32), size, health);
|
UI::renderBar(0, vec2(UI::width - 32 - size.x, 32), size, health);
|
||||||
|
|
||||||
|
if (!inventory.active && !lara->emptyHands()) { // ammo
|
||||||
|
int index = inventory.contains(lara->getCurrentWeaponInv());
|
||||||
|
if (index > -1)
|
||||||
|
inventory.renderItemCount(inventory.items[index], vec2(UI::width - 32 - size.x, 64), size.x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lara->stand == Lara::STAND_ONWATER || lara->stand == Character::STAND_UNDERWATER)
|
if (lara->stand == Lara::STAND_ONWATER || lara->stand == Character::STAND_UNDERWATER)
|
||||||
UI::renderBar(1, vec2(UI::width - 32 - size.x, 32), size, oxygen);
|
UI::renderBar(1, vec2(32, 32), size, oxygen);
|
||||||
|
|
||||||
inventory.renderUI();
|
inventory.renderUI();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user