bool tutorial_game::init(game *g) { g->turn = HOURS(12); // Start at noon for (int i = 0; i < NUM_LESSONS; i++) tutorials_seen[i] = false; // Set the scent map to 0 for (int i = 0; i < SEEX * MAPSIZE; i++) { for (int j = 0; j < SEEX * MAPSIZE; j++) g->scent(i, j) = 0; } g->temperature = 65; // We use a Z-factor of 10 so that we don't plop down tutorial rooms in the // middle of the "real" game world g->u.normalize(g); g->u.str_cur = g->u.str_max; g->u.per_cur = g->u.per_max; g->u.int_cur = g->u.int_max; g->u.dex_cur = g->u.dex_max; g->u.name = "John Smith"; g->levx = 100; g->levy = 100; g->cur_om = overmap(g, 0, 0, TUTORIAL_Z - 1); g->cur_om.make_tutorial(); g->cur_om.save(g->u.name, 0, 0, TUTORIAL_Z - 1); g->cur_om = overmap(g, 0, 0, TUTORIAL_Z); g->cur_om.make_tutorial(); g->u.toggle_trait(PF_QUICK); g->u.inv.push_back(item(g->itypes[itm_lighter], 0, 'e')); g->u.skillLevel("gun").level(5); g->u.skillLevel("melee").level(5); // Init the starting map at g location. for (int i = 0; i <= MAPSIZE; i += 2) { for (int j = 0; j <= MAPSIZE; j += 2) { tinymap tm(&g->itypes, &g->mapitems, &g->traps); tm.generate(g, &(g->cur_om), g->levx + i - 1, g->levy + j - 1, int(g->turn)); } } // Start with the overmap revealed for (int x = 0; x < OMAPX; x++) { for (int y = 0; y < OMAPY; y++) g->cur_om.seen(x, y) = true; } g->m.load(g, g->levx, g->levy); g->levz = 0; g->u.posx = SEEX + 2; g->u.posy = SEEY + 4; return true; }
bool defense_game::init(game *g) { g->turn = HOURS(12); // Start at noon g->temperature = 65; if (!g->u.create(g, PLTYPE_CUSTOM)) return false; g->u.str_cur = g->u.str_max; g->u.per_cur = g->u.per_max; g->u.int_cur = g->u.int_max; g->u.dex_cur = g->u.dex_max; init_itypes(g); init_mtypes(g); init_constructions(g); init_recipes(g); current_wave = 0; hunger = false; thirst = false; sleep = false; zombies = false; specials = false; spiders = false; triffids = false; robots = false; subspace = false; mercenaries = false; init_to_style(DEFENSE_EASY); setup(); g->u.cash = initial_cash; popup_nowait("Please wait as the map generates [ 0%]"); // TODO: support multiple defence games? clean up old defence game g->cur_om = overmap(g, 0, 0); init_map(g); caravan(g); return true; }
void monster::die(game *g) { if (!dead) dead = true; // Drop goodies int total_chance = 0, total_it_chance, cur_chance, selected_location, selected_item; bool animal_done = false; std::vector<items_location_and_chance> it = g->monitems[type->id]; std::vector<itype_id> mapit; if (type->item_chance != 0 && it.size() == 0) debugmsg("Type %s has item_chance %d but no items assigned!", type->name.c_str(), type->item_chance); else { for (int i = 0; i < it.size(); i++) total_chance += it[i].chance; while (rng(0, 99) < abs(type->item_chance) && !animal_done) { cur_chance = rng(1, total_chance); selected_location = -1; while (cur_chance > 0) { selected_location++; cur_chance -= it[selected_location].chance; } total_it_chance = 0; mapit = g->mapitems[it[selected_location].loc]; for (int i = 0; i < mapit.size(); i++) total_it_chance += g->itypes[mapit[i]]->rarity; cur_chance = rng(1, total_it_chance); selected_item = -1; while (cur_chance > 0) { selected_item++; cur_chance -= g->itypes[mapit[selected_item]]->rarity; } g->m.add_item(posx, posy, g->itypes[mapit[selected_item]], 0); if (type->item_chance < 0) animal_done = true; // Only drop ONE item. } } // Done dropping items // If we're a queen, make nearby groups of our type start to die out if (has_flag(MF_QUEEN)) { std::vector<mongroup*> groups = g->cur_om.monsters_at(g->levx, g->levy); for (int i = 0; i < groups.size(); i++) { moncat_id moncat_type = groups[i]->type; bool match = false; for (int j = 0; !match && j < g->moncats[moncat_type].size(); j++) { if (g->moncats[moncat_type][j] == type->id) match = true; } if (match) groups[i]->dying = true; } // Do it for overmap above/below too overmap tmp; if (g->cur_om.posz == 0) tmp = overmap(g, g->cur_om.posx, g->cur_om.posy, -1); else tmp = overmap(g, g->cur_om.posx, g->cur_om.posy, 0); groups = tmp.monsters_at(g->levx, g->levy); for (int i = 0; i < groups.size(); i++) { moncat_id moncat_type = groups[i]->type; bool match = false; for (int j = 0; !match && j < g->moncats[moncat_type].size(); j++) { if (g->moncats[moncat_type][j] == type->id) match = true; } if (match) groups[i]->dying = true; } } // If we're a mission monster, update the mission if (mission_id != -1) { mission_type *misstype = g->find_mission_type(mission_id); if (misstype->goal == MGOAL_FIND_MONSTER) g->fail_mission(mission_id); if (misstype->goal == MGOAL_KILL_MONSTER) g->mission_step_complete(mission_id, 1); } // Also, perform our death function mdeath md; (md.*type->dies)(g, this); // If our species fears seeing one of our own die, process that int anger_adjust = 0, morale_adjust = 0; for (int i = 0; i < type->anger.size(); i++) { if (type->anger[i] == MTRIG_FRIEND_DIED) anger_adjust += 15; } for (int i = 0; i < type->placate.size(); i++) { if (type->placate[i] == MTRIG_FRIEND_DIED) anger_adjust -= 15; } for (int i = 0; i < type->fear.size(); i++) { if (type->fear[i] == MTRIG_FRIEND_DIED) morale_adjust -= 15; } if (anger_adjust != 0 && morale_adjust != 0) { int light = g->light_level(); for (int i = 0; i < g->z.size(); i++) { int t = 0; if (g->m.sees(g->z[i].posx, g->z[i].posy, posx, posy, light, t)) { g->z[i].morale += morale_adjust; g->z[i].anger += anger_adjust; } } } }
void computer::activate_function(game *g, computer_action action) { switch (action) { case COMPACT_NULL: break; // Why would this be called? case COMPACT_OPEN: g->m.translate(t_door_metal_locked, t_floor); print_line("Doors opened."); break; case COMPACT_RELEASE: g->sound(g->u.posx, g->u.posy, 40, "An alarm sounds!"); g->m.translate(t_reinforced_glass_h, t_floor); g->m.translate(t_reinforced_glass_v, t_floor); print_line("Containment shields opened."); break; case COMPACT_TERMINATE: for (int x = 0; x < SEEX * 3; x++) { for (int y = 0; y < SEEY * 3; y++) { int mondex = g->mon_at(x, y); if (mondex != -1 && ((g->m.ter(x, y - 1) == t_reinforced_glass_h && g->m.ter(x, y + 1) == t_wall_h) || (g->m.ter(x, y + 1) == t_reinforced_glass_h && g->m.ter(x, y - 1) == t_wall_h))) g->kill_mon(mondex); } } print_line("Subjects terminated."); break; case COMPACT_PORTAL: for (int i = 0; i < SEEX * 3; i++) { for (int j = 0; j < SEEY * 3; j++) { int numtowers = 0; for (int xt = i - 2; xt <= i + 2; xt++) { for (int yt = j - 2; yt <= j + 2; yt++) { if (g->m.ter(xt, yt) == t_radio_tower) numtowers++; } } if (numtowers == 4) { if (g->m.tr_at(i, j) == tr_portal) g->m.tr_at(i, j) = tr_null; else g->m.add_trap(i, j, tr_portal); } } } break; case COMPACT_CASCADE: { if (!query_yn("WARNING: Resonance cascade carries severe risk! Continue?")) return; std::vector<point> cascade_points; for (int i = g->u.posx - 10; i <= g->u.posx + 10; i++) { for (int j = g->u.posy - 10; j <= g->u.posy + 10; j++) { if (g->m.ter(i, j) == t_radio_tower) cascade_points.push_back(point(i, j)); } } if (cascade_points.size() == 0) g->resonance_cascade(g->u.posx, g->u.posy); else { point p = cascade_points[rng(0, cascade_points.size() - 1)]; g->resonance_cascade(p.x, p.y); } } break; case COMPACT_RESEARCH: { int lines = 0, notes = 0; std::string log, tmp; int ch; std::ifstream fin; fin.open("data/LAB_NOTES"); if (!fin.is_open()) { debugmsg("Couldn't open ./data/LAB_NOTES for reading"); return; } while (fin.good()) { ch = fin.get(); if (ch == '%') notes++; } while (lines < 10) { fin.clear(); fin.seekg(0, std::ios::beg); fin.clear(); int choice = rng(1, notes); while (choice > 0) { getline(fin, tmp); if (tmp.find_first_of('%') == 0) choice--; } bool get_okay; getline(fin, tmp); do { lines++; if (lines < 15 && tmp.find_first_of('%') != 0) { log.append(tmp); log.append("\n"); } } while(tmp.find_first_of('%') != 0 && getline(fin, tmp)); } print_line(log.c_str()); print_line("Press any key..."); getch(); } break; case COMPACT_MAPS: { int minx = int(g->levx / 2) - 40; int maxx = int(g->levx / 2) + 40; int miny = int(g->levy / 2) - 40; int maxy = int(g->levy / 2) + 40; if (minx < 0) minx = 0; if (maxx >= OMAPX) maxx = OMAPX - 1; if (miny < 0) miny = 0; if (maxy >= OMAPY) maxy = OMAPY - 1; overmap tmp(g, g->cur_om.posx, g->cur_om.posy, 0); for (int i = minx; i <= maxx; i++) { for (int j = miny; j <= maxy; j++) tmp.seen(i, j) = true; } tmp.save(g->u.name, g->cur_om.posx, g->cur_om.posy, 0); print_line("Surface map data downloaded."); } break; case COMPACT_MISS_LAUNCH: { overmap tmp_om(g, g->cur_om.posx, g->cur_om.posy, 0); // Target Acquisition. point target = tmp_om.choose_point(g); if (target.x == -1) { print_line("Launch canceled."); return; } // Figure out where the glass wall is... int wall_spot = 0; for (int i = 0; i < SEEX * 3 && wall_spot == 0; i++) { if (g->m.ter(i, 10) == t_wall_glass_v) wall_spot = i; } // ...and put radioactive to the right of it for (int i = wall_spot + 1; i < SEEX * 2 - 1; i++) { for (int j = 1; j < SEEY * 2 - 1; j++) { if (one_in(3)) g->m.add_field(NULL, i, j, fd_nuke_gas, 3); } } // For each level between here and the surface, remove the missile for (int level = g->cur_om.posz; level < 0; level++) { tmp_om = g->cur_om; g->cur_om = overmap(g, tmp_om.posx, tmp_om.posy, level); map tmpmap(&g->itypes, &g->mapitems, &g->traps); tmpmap.load(g, g->levx, g->levy); tmpmap.translate(t_missile, t_hole); tmpmap.save(&tmp_om, g->turn, g->levx, g->levy); } g->cur_om = tmp_om; for (int x = target.x - 2; x <= target.x + 2; x++) { for (int y = target.y - 2; y <= target.y + 2; y++) g->nuke(x, y); } } break; case COMPACT_MISS_DISARM: // TODO: This! break; } // switch (action) }