/*! \brief Enemy initialisation * * This is the main enemy initialization routine. This function sets up * the enemy types and then loads each one in. It also calls a helper * function or two to complete the process. * * The encounter table consists of several 'sub-tables', grouped by * encounter number. Each row is one possible battle. * Fills in the cf[] array of enemies to load. * * \param en Encounter number in the Encounter table. * \param etid If =99, select a random row with that encounter number, * otherwise select row etid. * \returns number of random encounter */ int select_encounter (int en, int etid) { size_t i, p, j; int stop = 0, where = 0, entry = -1; while (!stop) { if (erows[where].tnum == en) stop = 1; else where++; if (where >= NUM_ETROWS) { sprintf (strbuf, _("There are no rows for encounter table #%d!"), en); program_death (strbuf); } } if (etid == 99) { i = rand () % 100 + 1; while (entry < 0) { if (i <= erows[where].per) { entry = where; } else where++; if (erows[where].tnum > en || where >= NUM_ETROWS) program_death (_("Couldn't select random encounter table row!")); } } else entry = where + etid; p = 0; for (j = 0; j < 5; j++) { if (erows[entry].idx[j] > 0) { cf[p] = erows[entry].idx[j] - 1; p++; } } num_enemies = p; /* adjust 'too hard' combat where player is alone and faced by >2 enemies */ if (num_enemies > 2 && numchrs == 1 && erows[entry].lvl + 2 > party[pidx[0]].lvl && etid == 99) num_enemies = 2; if (num_enemies == 0) program_death (_("Empty encounter table row!")); return entry; }
/*! \brief Read a command and parameter from a script * * This processes entity commands from the movement script. * This is from Verge1. * * Script commands are: * - U,R,D,L + param: move up, right, down, left by param spaces * - W+param: wait param frames * - B: start script again * - X+param: move to x-coord param * - Y+param: move to y-coord param * - F+param: face direction param (0=S, 1=N, 2=W, 3=E) * - K: kill (remove) entity * * \param target_entity Entity to process */ static void getcommand(t_entity target_entity) { char s; /* PH FIXME: prevented from running off end of string */ if (g_ent[target_entity].sidx < sizeof(g_ent[target_entity].script)) { s = g_ent[target_entity].script[g_ent[target_entity].sidx++]; } else { s = '\0'; } switch (s) { case 'u': case 'U': g_ent[target_entity].cmd = COMMAND_MOVE_UP; parsems(target_entity); break; case 'd': case 'D': g_ent[target_entity].cmd = COMMAND_MOVE_DOWN; parsems(target_entity); break; case 'l': case 'L': g_ent[target_entity].cmd = COMMAND_MOVE_LEFT; parsems(target_entity); break; case 'r': case 'R': g_ent[target_entity].cmd = COMMAND_MOVE_RIGHT; parsems(target_entity); break; case 'w': case 'W': g_ent[target_entity].cmd = COMMAND_WAIT; parsems(target_entity); break; case '\0': g_ent[target_entity].cmd = COMMAND_FINISH_COMMANDS; g_ent[target_entity].movemode = MM_STAND; g_ent[target_entity].cmdnum = 0; g_ent[target_entity].sidx = 0; break; case 'b': case 'B': g_ent[target_entity].cmd = COMMAND_REPEAT; break; case 'x': case 'X': g_ent[target_entity].cmd = COMMAND_MOVETO_X; parsems(target_entity); break; case 'y': case 'Y': g_ent[target_entity].cmd = COMMAND_MOVETO_Y; parsems(target_entity); break; case 'f': case 'F': g_ent[target_entity].cmd = COMMAND_FACE; parsems(target_entity); break; case 'k': case 'K': /* PH add: command K makes the ent disappear */ g_ent[target_entity].cmd = COMMAND_KILL; g_ent[target_entity].active = 0; break; default: #ifdef DEBUGMODE if (debugging > 0) { sprintf(strbuf, _("Invalid entity command (%c) at position %d for ent %d"), s, g_ent[target_entity].sidx, target_entity); program_death(strbuf); } #endif break; } }
/*! \brief Load all enemies from disk * * Loads up enemies from the *.mon files and fills the enemies[] array. * \author PH * \date 2003???? */ static void load_enemies (void) { int i, tmp, lx, ly, p; FILE *edat; s_fighter *f; if (enemies != NULL) { /* Already done the loading */ return; } enemy_pcx = load_datafile_object (PCX_DATAFILE, "ENEMY_PCX"); if (enemy_pcx == NULL) { program_death (_("Could not load enemy sprites from datafile!")); } edat = fopen (kqres (DATA_DIR, "allstat.mon"), "r"); if (!edat) program_death (_("Could not load 1st enemy datafile!")); enemies_n = 0; enemies_cap = 128; enemies = (s_fighter **) malloc (sizeof (s_fighter *) * enemies_cap); // Loop through for every monster in allstat.mon while (fscanf (edat, "%s", strbuf) != EOF) { if (enemies_n >= enemies_cap) { enemies_cap *= 2; enemies = (s_fighter **) realloc (enemies, sizeof (s_fighter *) * enemies_cap); } f = enemies[enemies_n++] = (s_fighter *) malloc (sizeof (s_fighter)); memset (f, 0, sizeof (s_fighter)); // Enemy name strncpy (f->name, strbuf, sizeof (f->name)); // Index number (ignored; automatically generated) fscanf (edat, "%d", &tmp); // x-coord of image in datafile fscanf (edat, "%d", &tmp); lx = tmp; // y-coord of image in datafile fscanf (edat, "%d", &tmp); ly = tmp; // Image width fscanf (edat, "%d", &tmp); f->cw = tmp; // Image length (height) fscanf (edat, "%d", &tmp); f->cl = tmp; // Experience points earned fscanf (edat, "%d", &tmp); f->xp = tmp; // Gold received fscanf (edat, "%d", &tmp); f->gp = tmp; // Level fscanf (edat, "%d", &tmp); f->lvl = tmp; // Max HP fscanf (edat, "%d", &tmp); f->mhp = tmp; // Max MP fscanf (edat, "%d", &tmp); f->mmp = tmp; // Defeat Item Probability: chance of finding any items after defeat fscanf (edat, "%d", &tmp); f->dip = tmp; // Defeat Item Common: item found commonly of the time fscanf (edat, "%d", &tmp); f->defeat_item_common = tmp; // Defeat Item Rare: item found rarely fscanf (edat, "%d", &tmp); f->defeat_item_rare = tmp; // Steal Item Common: item found commonly from stealing fscanf (edat, "%d", &tmp); f->steal_item_common = tmp; // Steal Item Rare: item found rarely when stealing fscanf (edat, "%d", &tmp); f->steal_item_rare = tmp; // Enemy's strength (agility & vitality set to zero) fscanf (edat, "%d", &tmp); f->stats[A_STR] = tmp; f->stats[A_AGI] = 0; f->stats[A_VIT] = 0; // Intelligence & Sagacity (both the same) fscanf (edat, "%d", &tmp); f->stats[A_INT] = tmp; f->stats[A_SAG] = tmp; // Defense against: Speed, Spirit, Attack, Hit, Defence, Evade, Magic (in that order) for (p = 5; p < 13; p++) { fscanf (edat, "%d", &tmp); f->stats[p] = tmp; } // Bonus fscanf (edat, "%d", &tmp); f->bonus = tmp; f->bstat = 0; // Current weapon type fscanf (edat, "%d", &tmp); f->cwt = tmp; // Weapon elemental type fscanf (edat, "%d", &tmp); f->welem = tmp; // Undead Level (defense against Undead attacks) fscanf (edat, "%d", &tmp); f->unl = tmp; // Critical attacks fscanf (edat, "%d", &tmp); f->crit = tmp; // Temp Sag & Int for Imbued fscanf (edat, "%d", &tmp); f->imb_s = tmp; // Imbued stat type (Spd, Spi, Att, Hit, Def, Evd, Mag) fscanf (edat, "%d", &tmp); f->imb_a = tmp; f->img = create_sub_bitmap ((BITMAP *) enemy_pcx->dat, lx, ly, f->cw, f->cl); for (p = 0; p < 2; p++) { fscanf (edat, "%d", &tmp); f->imb[p] = tmp; } } fclose (edat); edat = fopen (kqres (DATA_DIR, "resabil.mon"), "r"); if (!edat) program_death (_("Could not load 2nd enemy datafile!")); for (i = 0; i < enemies_n; i++) { f = enemies[i]; fscanf (edat, "%s", strbuf); fscanf (edat, "%d", &tmp); for (p = 0; p < R_TOTAL_RES; p++) { fscanf (edat, "%d", &tmp); f->res[p] = tmp; } for (p = 0; p < 8; p++) { fscanf (edat, "%d", &tmp); f->ai[p] = tmp; } for (p = 0; p < 8; p++) { fscanf (edat, "%d", &tmp); f->aip[p] = tmp; f->atrack[p] = 0; } f->hp = f->mhp; f->mp = f->mmp; for (p = 0; p < 24; p++) f->sts[p] = 0; f->aux = 0; f->mrp = 100; } fclose (edat); }