crossbow achievements

This commit is contained in:
Zeno Rogue 2023-12-21 19:51:05 +01:00
parent 0de012923a
commit 558b8d7aff
3 changed files with 69 additions and 4 deletions

View File

@ -10,7 +10,7 @@
#include "hyper.h"
namespace hr {
#define NUMLEADER 87
#define NUMLEADER 90
EX bool test_achievements = false;
@ -80,7 +80,10 @@ EX const char* leadernames[NUMLEADER] = {
"Lazurite Figurines", // 83
"Water Lilies", // 84
"Capon Stones", // 85
"Crystal Dice" // 86
"Crystal Dice", // 86
"Crossbow (bull)", // 87
"Crossbow (geodesic)", // 88
"Crossbow (geometric)", // 89
};
#define LB_STATISTICS 62
@ -109,7 +112,6 @@ EX bool wrongMode(char flags) {
if(casual) return true;
if(flags == rg::global) return false;
if(flags == rg::fail) return true;
if(bow::weapon) return true;
if(flags != rg::special_geometry && flags != rg::special_geometry_nicewalls) {
if(!BITRUNCATED) return true;
@ -630,6 +632,10 @@ EX void achievement_count(const string& s, int current, int prev) {
achievement_gain("BUG3");
if(s == "ELEC" && current >= 10)
achievement_gain("ELEC3");
if(s == "BOWVARIETY" && current >= 2)
achievement_gain("BOWVARIETY1");
if(s == "BOWVARIETY" && current >= 6)
achievement_gain("BOWVARIETY2");
}
int specific_improved = 0;
@ -655,7 +661,6 @@ EX void achievement_score(int cat, int number) {
#ifdef HAVE_ACHIEVEMENTS
if(cheater) return;
if(casual) return;
if(bow::weapon) return;
LATE( achievement_score(cat, number); )
if(disksize) return;
if(cat == LB_HALLOWEEN) {
@ -796,6 +801,9 @@ EX void achievement_final(bool really_final) {
if(PURE) specialcode+=4;
if(numplayers() > 1) specialcode+=8;
if(inv::on) specialcode+=16;
if(bow::crossbow_mode && bow::style == bow::cbBull) specialcode += 32;
if(bow::crossbow_mode && bow::style == bow::cbGeodesic) specialcode += 64;
if(bow::crossbow_mode && bow::style == bow::cbGeometric) specialcode += 96;
if(sphere && specialland == laHalloween) {
if(specialcode) return;
@ -822,6 +830,9 @@ EX void achievement_final(bool really_final) {
case 8: sid = 61; break;
case 9: sid = 44; break;
case 16: sid = 69; break;
case 32: sid = 87; break;
case 64: sid = 88; break;
case 96: sid = 89; break;
default: return;
}

View File

@ -2944,6 +2944,8 @@ EX }
EX namespace kraken {
EX map<cell*, bool> half_killed;
EX cell *head(cell *c) {
if(c->monst == moKrakenH) return c;
if(c->monst == moKrakenT) return c->move(c->mondir);
@ -3045,6 +3047,7 @@ EX namespace kraken {
c3->monst = moNone;
}
c->monst = moKrakenH;
if(half_killed.count(c2)) { half_killed[c] = half_killed[c2]; half_killed.erase(c2); }
vector<pair<cell*, cell*> > acells;
acells.push_back(make_pair(c2, c));
forCellIdEx(c3, i, c) {
@ -3516,6 +3519,7 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
clearing::stats.clear();
clearing::score.clear();
tortoise::emap.clear();
kraken::half_killed.clear();
tortoise::babymap.clear();
dragon::target = NULL;
#if CAP_FIELD
@ -3548,6 +3552,7 @@ auto ccm = addHook(hooks_clearmemory, 0, [] () {
addHook(hooks_removecells, 0, [] () {
for(cell *c: removed_cells) clearing::score.erase(c);
for(auto& am: adj_memo) am.clear();
for(cell *c: removed_cells) kraken::half_killed.erase(c);
eliminate_if(heat::offscreen_heat, is_cell_removed);
eliminate_if(heat::offscreen_fire, is_cell_removed);
eliminate_if(princess::infos, [] (princess::info*& i) {

View File

@ -374,6 +374,33 @@ EX void shoot() {
vector<bowpoint> pushes;
// for achievements
set<eMonster> kills;
vector<pair<cell*, int>> healthy_dragons;
map<cell*, pair<int, int>> kraken_hits;
int dragon_hits = 0;
// for achievements
for(auto& mov: bowpath) {
cell *c = mov.prev.at;
if(c->monst == moDragonHead) {
bool healthy = true;
cell *c1 = c;
int qty = 0;
for(int i=0; i<iteration_limit; i++) {
if(!isDragon(c1)) break;
if(!c1->hitpoints) { healthy = false; break; }
if(c1->mondir == NODIR) break;
c1 = c1->move(c1->mondir);
qty++;
}
if(healthy) healthy_dragons.emplace_back(c, qty);
}
if(c->monst == moKrakenT && c->hitpoints) {
kraken_hits[kraken::head(c)].first++;
}
}
for(auto& mov: bowpath) {
cell *c = mov.prev.at;
cell *cf = mov.prev.cpeek();
@ -401,6 +428,7 @@ EX void shoot() {
mirror::breakMirror(mov.next, -1);
eMonster m = c->monst;
if(!m || isMimic(m)) continue;
if(m == moKrakenH) continue;
if(!canAttack(cf, who, c, m, attackflags)) {
if(among(m, moSleepBull, moHerdBull)) {
@ -420,11 +448,16 @@ EX void shoot() {
bool push = (items[itCurseWeakness] || (isStunnable(c->monst) && c->hitpoints > 1));
push = push && (!(mov.flags & bpLAST) && monsterPushable(c));
// for achievements
if(isDragon(m)) dragon_hits++;
if(m == moKrakenT && c->hitpoints) kraken_hits[kraken::head(c)].second++;
if(m && attackMonster(c, attackflags | AF_MSG, who)) hit_anything = true;
if(!c->monst || isAnyIvy(m)) {
spread_plague(cf, c, movei(mov.prev).rev().d, moPlayer);
produceGhost(c, m, moPlayer);
kills.insert(m);
}
if(push) pushes.push_back(mov);
@ -446,6 +479,22 @@ EX void shoot() {
reverse(bowpath.begin(), bowpath.end());
// three achievements:
achievement_count("BOWVARIETY", kills.size(), 0);
for(auto p: healthy_dragons) {
cell *c = p.first;
if(c->monst != moDragonHead && dragon_hits >= p.second)
achievement_gain_once("BOWDRAGON");
}
for(auto kh: kraken_hits) {
if(kh.second.first == 3 && kh.second.second == 3) {
if(kraken::half_killed[kh.first]) achievement_gain_once("BOWKRAKEN");
else kraken::half_killed[kh.first] = true;
}
}
gen_bowpath_map();
}