mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-16 01:54:38 +02:00
#11 ammo counter
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
|
||||
#define MAX_LAYERS 4
|
||||
|
||||
#define UNLIMITED_AMMO 10000
|
||||
|
||||
struct Controller;
|
||||
|
||||
struct IGame {
|
||||
@@ -33,6 +35,7 @@ struct IGame {
|
||||
|
||||
virtual bool invUse(TR::Entity::Type item, TR::Entity::Type slot) { return false; }
|
||||
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; }
|
||||
};
|
||||
|
10
src/format.h
10
src/format.h
@@ -93,10 +93,10 @@
|
||||
E( INV_PASSPORT_CLOSED ) \
|
||||
E( INV_MAP ) \
|
||||
E( CRYSTAL ) \
|
||||
E( WEAPON_PISTOLS ) \
|
||||
E( WEAPON_SHOTGUN ) \
|
||||
E( WEAPON_MAGNUMS ) \
|
||||
E( WEAPON_UZIS ) \
|
||||
E( PISTOLS ) \
|
||||
E( SHOTGUN ) \
|
||||
E( MAGNUMS ) \
|
||||
E( UZIS ) \
|
||||
E( AMMO_PISTOLS ) \
|
||||
E( AMMO_SHOTGUN ) \
|
||||
E( AMMO_MAGNUMS ) \
|
||||
@@ -631,7 +631,7 @@ namespace TR {
|
||||
}
|
||||
|
||||
int isItem() {
|
||||
return (type >= WEAPON_PISTOLS && type <= AMMO_UZIS) ||
|
||||
return (type >= PISTOLS && type <= AMMO_UZIS) ||
|
||||
(type >= PUZZLE_1 && type <= PUZZLE_4) ||
|
||||
(type >= KEY_1 && type <= KEY_4) ||
|
||||
(type == MEDIKIT_SMALL || type == MEDIKIT_BIG || type == SCION_1); // TODO: recheck all items
|
||||
|
170
src/inventory.h
170
src/inventory.h
@@ -129,7 +129,7 @@ struct Inventory {
|
||||
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) {
|
||||
TR::Level *level = game->getLevel();
|
||||
@@ -145,16 +145,16 @@ struct Inventory {
|
||||
if (level->extra.inv.gamma != -1)
|
||||
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_MAGNUMS, 999);
|
||||
add(TR::Entity::INV_UZIS, 999);
|
||||
add(TR::Entity::INV_MEDIKIT_SMALL, 999);
|
||||
add(TR::Entity::INV_MEDIKIT_BIG, 999);
|
||||
add(TR::Entity::INV_UZIS, 10);
|
||||
// add(TR::Entity::INV_MEDIKIT_SMALL, 999);
|
||||
// add(TR::Entity::INV_MEDIKIT_BIG, 999);
|
||||
|
||||
add(TR::Entity::INV_SCION, 1);
|
||||
add(TR::Entity::INV_KEY_1, 1);
|
||||
add(TR::Entity::INV_PUZZLE_1, 1);
|
||||
// add(TR::Entity::INV_SCION, 1);
|
||||
// add(TR::Entity::INV_KEY_1, 1);
|
||||
// add(TR::Entity::INV_PUZZLE_1, 1);
|
||||
|
||||
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
||||
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
||||
@@ -164,6 +164,9 @@ struct Inventory {
|
||||
}
|
||||
|
||||
~Inventory() {
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
delete items[i];
|
||||
|
||||
for (int i = 0; i < COUNT(background); i++)
|
||||
delete background[i];
|
||||
}
|
||||
@@ -172,9 +175,41 @@ struct Inventory {
|
||||
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) {
|
||||
type = convToInv(type);
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
if (items[i].type == type)
|
||||
if (items[i]->type == type)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
@@ -182,15 +217,17 @@ struct Inventory {
|
||||
void add(TR::Entity::Type type, int count = 1) {
|
||||
int i = contains(type);
|
||||
if (i > -1) {
|
||||
items[i].count += count;
|
||||
items[i]->count += count;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(itemsCount < INVENTORY_MAX_ITEMS);
|
||||
|
||||
type = convToInv(type);
|
||||
|
||||
int pos = 0;
|
||||
for (int pos = 0; pos < itemsCount; pos++)
|
||||
if (items[pos].type > type)
|
||||
if (items[pos]->type > type)
|
||||
break;
|
||||
|
||||
if (pos - itemsCount) {
|
||||
@@ -198,36 +235,52 @@ struct Inventory {
|
||||
items[i] = items[i - 1];
|
||||
}
|
||||
|
||||
Item it(game->getLevel(), type, count);
|
||||
items[pos] = it;
|
||||
items[pos] = new Item(game->getLevel(), type, count);
|
||||
itemsCount++;
|
||||
}
|
||||
|
||||
int getCount(TR::Entity::Type type) {
|
||||
int* getCountPtr(TR::Entity::Type type) {
|
||||
int i = contains(type);
|
||||
if (i < 0) return 0;
|
||||
return items[i].count;
|
||||
if (i < 0) return NULL;
|
||||
return &items[i]->count;
|
||||
}
|
||||
|
||||
void remove(TR::Entity::Type type, int count = 1) {
|
||||
int i = contains(type);
|
||||
if (i > -1)
|
||||
items[i].count -= count;
|
||||
int idx = contains(type);
|
||||
if (idx > -1) {
|
||||
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) {
|
||||
if (item == TR::Entity::NONE) {
|
||||
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::PUZZLE_1; break;
|
||||
default : return false;
|
||||
}
|
||||
switch (slot) {
|
||||
case TR::Entity::PUZZLE_HOLE_1 : item = TR::Entity::INV_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;
|
||||
}
|
||||
|
||||
if (getCount(item) > 0) {
|
||||
if (getCountPtr(item)) {
|
||||
remove(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -240,7 +293,7 @@ struct Inventory {
|
||||
|
||||
if (active) {
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
items[i].reset();
|
||||
items[i]->reset();
|
||||
|
||||
phasePage = 1.0f;
|
||||
phaseSelect = 1.0f;
|
||||
@@ -269,7 +322,7 @@ struct Inventory {
|
||||
|
||||
int getItemIndex(Page page, int index) {
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
if (items[i].desc.page == page) {
|
||||
if (items[i]->desc.page == page) {
|
||||
if (!index)
|
||||
return i;
|
||||
index--;
|
||||
@@ -285,7 +338,7 @@ struct Inventory {
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < itemsCount; i++)
|
||||
if (items[i].desc.page == page)
|
||||
if (items[i]->desc.page == page)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
@@ -293,7 +346,7 @@ struct Inventory {
|
||||
|
||||
bool showHealthBar() {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -329,15 +382,15 @@ struct Inventory {
|
||||
|
||||
vec3 p;
|
||||
|
||||
Item &item = items[getItemIndex(page, index)];
|
||||
Item *item = items[getItemIndex(page, index)];
|
||||
|
||||
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;
|
||||
if (!chosen) {
|
||||
item.angle = 0.0f;
|
||||
item->angle = 0.0f;
|
||||
} 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_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;
|
||||
@@ -347,7 +400,7 @@ struct Inventory {
|
||||
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;
|
||||
}
|
||||
item.choose();
|
||||
item->choose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,8 +410,8 @@ struct Inventory {
|
||||
int itemIndex = index == targetIndex ? getItemIndex(page, index) : -1;
|
||||
|
||||
for (int i = 0; i < itemsCount; i++) {
|
||||
items[i].update();
|
||||
float &angle = items[i].angle;
|
||||
items[i]->update();
|
||||
float &angle = items[i]->angle;
|
||||
|
||||
if (itemIndex != i || chosen) {
|
||||
if (angle == 0.0f) {
|
||||
@@ -378,8 +431,8 @@ struct Inventory {
|
||||
angle = clampAngle(angle);
|
||||
}
|
||||
|
||||
if (ready && chosen && phaseChoose == 1.0f && item.anim->isEnded) {
|
||||
TR::Entity::Type type = item.type;
|
||||
if (ready && chosen && phaseChoose == 1.0f && item->anim->isEnded) {
|
||||
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 ||
|
||||
type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG) {
|
||||
@@ -420,26 +473,29 @@ struct Inventory {
|
||||
Core::setDepthTest(true);
|
||||
}
|
||||
|
||||
void renderItemText(const Item &item, float width) {
|
||||
UI::textOut(game, vec2(0, 480 - 16), item.desc.name, UI::aCenter, width);
|
||||
|
||||
if (item.count > 1) {
|
||||
char spec;
|
||||
switch (item.type) {
|
||||
case TR::Entity::INV_SHOTGUN : spec = 12; break;
|
||||
case TR::Entity::INV_MAGNUMS : spec = 13; break;
|
||||
case TR::Entity::INV_UZIS : spec = 14; break;
|
||||
default : spec = 0;
|
||||
}
|
||||
void renderItemCount(const Item *item, const vec2 &pos, float width) {
|
||||
char spec;
|
||||
switch (item->type) {
|
||||
case TR::Entity::INV_SHOTGUN : spec = 12; break;
|
||||
case TR::Entity::INV_MAGNUMS : spec = 13; break;
|
||||
case TR::Entity::INV_UZIS : spec = 14; break;
|
||||
default : spec = 0;
|
||||
}
|
||||
|
||||
if ((item->count > 1 || spec) && item->count < UNLIMITED_AMMO) {
|
||||
char buf[16];
|
||||
sprintf(buf, "%d %c", item.count, spec);
|
||||
sprintf(buf, "%d %c", item->count, spec);
|
||||
for (int i = 0; buf[i] != ' '; i++)
|
||||
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) {
|
||||
float phase = page == targetPage ? phasePage : (1.0f - phasePage);
|
||||
|
||||
@@ -462,13 +518,13 @@ struct Inventory {
|
||||
|
||||
int itemIndex = 0;
|
||||
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;
|
||||
|
||||
float a = getAngle(itemIndex, count) - angle - collapseAngle;
|
||||
float ia = item.angle;
|
||||
float ia = item->angle;
|
||||
float ra = ringTilt;
|
||||
float rd = radius;
|
||||
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(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++;
|
||||
}
|
||||
|
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 State { IS_HIDDEN, IS_ARMED, IS_FIRING };
|
||||
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 wpnNext;
|
||||
Weapon::State wpnState;
|
||||
int *wpnAmmo;
|
||||
vec3 chestOffset;
|
||||
|
||||
struct Arm {
|
||||
@@ -406,18 +405,9 @@ struct Lara : Character {
|
||||
getEntity().flags.active = 1;
|
||||
initMeshOverrides();
|
||||
|
||||
weapons[Weapon::PISTOLS].ammo = -1;
|
||||
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;
|
||||
if (!home)
|
||||
wpnSet(Weapon::PISTOLS);
|
||||
} else
|
||||
else
|
||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||
|
||||
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(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(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
||||
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
||||
//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(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
|
||||
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
|
||||
@@ -498,10 +488,24 @@ struct Lara : Character {
|
||||
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) {
|
||||
wpnCurrent = wType;
|
||||
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]);
|
||||
|
||||
wpnSetAnim(arms[0], Weapon::IS_HIDDEN, Weapon::Anim::NONE, 0.0f, 0.0f);
|
||||
@@ -576,7 +580,7 @@ struct Lara : Character {
|
||||
if (wpnCurrent != Weapon::SHOTGUN) {
|
||||
meshSwap(1, level->extra.weapons[wpnCurrent], mask);
|
||||
// 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 {
|
||||
meshSwap(2, level->extra.weapons[wpnCurrent], mask);
|
||||
}
|
||||
@@ -755,7 +759,7 @@ struct Lara : Character {
|
||||
|
||||
float nearDist = 32.0f * 1024.0f;
|
||||
vec3 nearPos;
|
||||
bool hasShot = false;
|
||||
int shots = 0;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int armIndex;
|
||||
@@ -768,8 +772,15 @@ struct Lara : Character {
|
||||
}
|
||||
Arm *arm = &arms[armIndex];
|
||||
|
||||
if (wpnAmmo && *wpnAmmo != UNLIMITED_AMMO) {
|
||||
if (*wpnAmmo <= 0)
|
||||
continue;
|
||||
if (wpnCurrent != Weapon::SHOTGUN)
|
||||
*wpnAmmo -= 1;
|
||||
}
|
||||
|
||||
arm->shotTimer = 0.0f;
|
||||
hasShot = true;
|
||||
shots++;
|
||||
|
||||
int joint = wpnCurrent == Weapon::SHOTGUN ? 8 : (i ? 11 : 8);
|
||||
|
||||
@@ -798,9 +809,16 @@ struct Lara : Character {
|
||||
Core::lightColor[1 + armIndex] = FLASH_LIGHT_COLOR;
|
||||
}
|
||||
|
||||
if (hasShot) {
|
||||
if (shots) {
|
||||
playSound(wpnGetSound(), pos, 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);
|
||||
}
|
||||
|
||||
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 {
|
||||
if (level.version == TR::Level::VER_TR1_PSX && id == TR::SND_SECRET)
|
||||
return NULL;
|
||||
@@ -979,11 +983,18 @@ struct Level : IGame {
|
||||
if (oxygen <= 0.2f) oxygen = 0.0f;
|
||||
}
|
||||
|
||||
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f)))
|
||||
UI::renderBar(0, vec2(32, 32), size, health);
|
||||
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f))) {
|
||||
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)
|
||||
UI::renderBar(1, vec2(UI::width - 32 - size.x, 32), size, oxygen);
|
||||
UI::renderBar(1, vec2(32, 32), size, oxygen);
|
||||
|
||||
inventory.renderUI();
|
||||
|
||||
|
Reference in New Issue
Block a user