#include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "mud.h" SOCIETY_DATA * new_society (void) { SOCIETY_DATA *soc; int i; soc = mem_alloc (sizeof (*soc)); soc->next = NULL; soc->vnum = 0; soc->name = str_dup ("New Society"); soc->room_start_vnum = 0; soc->flags = 0; soc->num_start_rooms = 0; for (i = 0; i < NUM_CASTES; i++) soc->caste[i] = NULL; soc->next = society_list; society_list = soc; return soc; } CASTE_DATA *new_caste (void) { CASTE_DATA *caste; int i; caste = mem_alloc (sizeof (*caste)); caste->num_ranks = MAX_CASTE_RANKS; caste->mob_start_vnum = 0; caste->flags = 0; caste->name = str_dup ("New Caste"); for (i = 0; i < MAX_CASTE_RANKS; i++) { caste->chance_to_advance[i] = 0; caste->curr_pop[i] = 0; caste->max_pop[i] = 0; } return caste; } void load_society (void) { FILE *fp; char society_fname[100]; sprintf (society_fname, "society.dat"); if ((fp = fopen (society_fname, "r")) == NULL) { fprintf (stderr, "No Society Data To Load!\n"); return; } for (;;) { char letter; char *word; letter = fread_letter (fp); if (letter != '#') { bug ("Load_Society: # not found.", 0); break; } word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp (word, "SOCIETY")) { fread_society (fp); } else if (!str_cmp (word, "END")) break; else { bug ("Load_society: bad section.", 0); break; } } fclose (fp); return; } void fread_society (FILE *fp) { SOCIETY_DATA *soc; int j; int curr_caste = 0; soc = new_society (); for (;;) { char *word; word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp (word, "END")) break; else if (!str_cmp (word, "Vnum")) { soc->vnum = fread_number (fp); top_society = UMAX (top_society, soc->vnum); } else if (!str_cmp (word, "Name")) soc->name = str_dup (fread_string (fp, NULL)); else if (!str_cmp (word, "RoomStart")) soc->room_start_vnum = fread_number (fp); else if (!str_cmp (word, "RoomNumber")) soc->num_start_rooms = fread_number (fp); else if (!str_cmp (word, "SFlags")) soc->flags = fread_number (fp); else if (!str_cmp (word, "Caste")) { curr_caste = fread_number (fp); if (curr_caste < 0 || curr_caste >= NUM_CASTES) continue; if (!soc->caste[curr_caste]) soc->caste[curr_caste] = new_caste (); for (;;) { word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp (word, "END")) break; else if (!str_cmp (word, "NumRanks")) soc->caste[curr_caste]->num_ranks = fread_number (fp); else if (!str_cmp (word, "Name")) { if (soc->caste[curr_caste]->name) free_string (soc->caste[curr_caste]->name); soc->caste[curr_caste]->name = str_dup (fread_string (fp, NULL)); } else if (!str_cmp (word, "StartMob")) soc->caste[curr_caste]->mob_start_vnum = fread_number (fp); else if (!str_cmp (word, "CFlags")) soc->caste[curr_caste]->flags = fread_number (fp); else if (!str_cmp (word, "AdvanceChance")) { for (j = 0; j < MAX_CASTE_RANKS; j++) soc->caste[curr_caste]->chance_to_advance[j] = fread_number(fp); } else if (!str_cmp (word, "MaxPop")) { for (j = 0; j < MAX_CASTE_RANKS; j++) soc->caste[curr_caste]->max_pop[j] = fread_number(fp); } } } } return; } void save_society (void) { int i; SOCIETY_DATA *soc; char society_fname[100]; FILE *fp; sprintf (society_fname, "society.dat"); if ((fp = fopen (society_fname, "w")) == NULL) { fprintf (stderr, "BAD WRITE ON SOCIETY DATA!!!"); perror (society_fname); } for (soc = society_list; soc != NULL; soc = soc->next) { if (!soc->caste[0] || soc->caste[0]->chance_to_advance[0] == 0) continue; fprintf (fp, "#SOCIETY\n"); fprintf (fp, "Vnum %d\n", soc->vnum); fprintf (fp, "Name %s~\n", fix_string (soc->name)); fprintf (fp, "RoomStart %d\n", soc->room_start_vnum); fprintf (fp, "RoomNumber %d\n", soc->num_start_rooms); fprintf (fp, "SFlags %d\n", soc->flags); for (i = 0; i < NUM_CASTES; i++) { if (soc->caste[i]) { fwrite_caste (soc, i , fp); } } fprintf (fp, "END\n"); } fprintf (fp, "#END\n"); fclose (fp); return; } void copy_society (SOCIETY_DATA *old, SOCIETY_DATA *new) { int i, j; new->name = str_dup (old->name); new->room_start_vnum = old->room_start_vnum; new->num_start_rooms = old->num_start_rooms; new->vnum = old->vnum; new->flags = old->flags; for (i = 0; i < NUM_CASTES; i++) { if (old->caste[i]) { CASTE_DATA *cst, *ocst; cst = new_caste(); ocst = old->caste[i]; cst->name = str_dup (ocst->name); cst->num_ranks = ocst->num_ranks; cst->mob_start_vnum = ocst->mob_start_vnum; cst->flags = ocst->flags; for (j = 0;j < MAX_CASTE_RANKS; j++) { cst->chance_to_advance[j] = ocst->chance_to_advance[j]; cst->max_pop[j] = number_range (ocst->max_pop[j]*3/4, ocst->max_pop[j]*5/4); cst->curr_pop[j] = 0; } new->caste[i] = cst; } } return; } void fwrite_caste (SOCIETY_DATA *soc, int num, FILE *fp) { int i; CASTE_DATA *caste; if (!soc->caste[num]) return; else caste = soc->caste[num]; fprintf (fp, "Caste %d\n", num); fprintf (fp, "NumRanks %d\n", caste->num_ranks); fprintf (fp, "Name %s~\n", fix_string (caste->name)); fprintf (fp, "StartMob %d\n", caste->mob_start_vnum); fprintf (fp, "CFlags %d\n", caste->flags); fprintf (fp, "AdvanceChance "); for (i = 0; i < MAX_CASTE_RANKS; i++) { fprintf (fp, "%d ", caste->chance_to_advance[i]); } fprintf (fp, "\n"); fprintf (fp, "MaxPop "); for (i = 0; i < MAX_CASTE_RANKS; i++) { fprintf (fp, "%d ", caste->max_pop[i]); } fprintf (fp, "\nEND\n"); return; } void save_mobile_info (void) { FILE *fp; char mob_filename[100]; AFFECT_DATA *paf; int iHash; ROOM_DATA *room; CHAR_DATA *rch; RESET_DATA *reset; bool found = FALSE; sprintf (mob_filename, "mobiles.dat"); if ((fp = fopen (mob_filename, "w")) == NULL) { perror ("mobiles.dat"); return; } for (iHash = 0; iHash < HASH_MAX; iHash++) { for (room = room_hash[iHash]; room != NULL; room = room->next) { for (rch = room->people; rch != NULL; rch = rch->next_in_room) { found = FALSE; if (IS_PLAYER (rch) || rch->data_type == 50 || !rch->in_room) continue; if (!rch->society) { for (reset = room->resets; reset != NULL; reset = reset->next) { if (reset->command == 'M' && reset->rs_vnum == rch->pIndexData->vnum) { found = TRUE; break; } } } if (found) continue; fprintf (fp, "#Mob %d %d %d %ld %ld %d %d %d %s~\n", rch->pIndexData->vnum, rch->in_room->vnum, rch->society, rch->hit, rch->max_hit, rch->move, rch->max_move, ((MASTER (rch) && IS_MOB (MASTER (rch)) && MASTER(rch)->in_room == rch->in_room) ? MASTER(rch)->pIndexData->vnum : 0), (HUNTING (rch) ? HUNTING (rch) : "none")); for (paf = rch->affected; paf && paf != NULL; paf = paf->next) { fprintf (fp, "AffectData %d %d %d %d %d %d %d %d\n", paf->type, paf->duration, paf->modifier, paf->location, paf->aff[0], paf->aff[1], paf->aff[2], paf->aff[3]); } if (rch->carrying) fwrite_obj (rch, rch->carrying, fp, 0); fprintf (fp, "END\n"); } } } fprintf (fp, "\n\n#END\n\n"); fclose (fp); return; } void save_object_info (void) { FILE *fp; char obj_filename[100]; int hash; ROOM_DATA *room; sprintf (obj_filename, "objects.dat"); if ((fp = fopen (obj_filename, "w")) == NULL) { perror ("Could not open objects.dat for write."); return; } for (hash = 0; hash < HASH_MAX; hash++) { for (room = room_hash[hash]; room != NULL; room = room->next) { if (room->contents) { fwrite_obj (NULL, room->contents, fp, 0); } } } fprintf (fp, "\n\n#END\n\n"); fclose (fp); } void fread_and_place_objects (void) { FILE *fp; char obj_filename[100]; sprintf (obj_filename , "objects.dat"); if ((fp = fopen (obj_filename, "r")) == NULL) { fprintf (stderr, "No objects data to load up!\n"); return; } for (;;) { char letter; char *word; letter = fread_letter (fp); if (letter != '#') break; word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp (word, "END")) break; if (!str_cmp (word, "OBJECT")) fread_obj (NULL, fp , 100); } fclose (fp); return; } void fread_and_place_mobiles (void) { FILE *fp; char mob_filename[100]; CHAR_DATA *ch, *rch; int follownum, i; sprintf (mob_filename , "mobiles.dat"); if ((fp = fopen (mob_filename, "r")) == NULL) { fprintf (stderr, "No mobiles data to load up!\n"); return; } for (;;) { char letter; char *word; letter = fread_letter (fp); if (letter != '#') { fprintf (stderr, "Missing # in mobiles.dat.\n"); break; } word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp (word, "Mob")) { place_one_mob (fp); } else if (!str_cmp (word, "END")) break; else { fprintf (stderr, "BAD WORD READ IN MOBILES.DAT: %s\n", word); } } fclose (fp); for (i = 0; i < TOTAL_LIST; i++) { for (ch = char_list[i]; ch != NULL; ch = ch->next) { if (ch->fgt && ch->fgt->hunting && is_number (ch->fgt->hunting)) { follownum = atoi (ch->fgt->hunting); free_string (ch->fgt->hunting); ch->fgt->hunting = NULL; for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room) { if (rch == ch || IS_PLAYER (rch) || rch->pIndexData->vnum != follownum) continue; add_follower (ch, rch); break; } } } } return; } void place_one_mob (FILE *fp) { int vnum; CHAR_DATA *ch; MOB_PROTOTYPE *pMob; int room_num, i; ROOM_DATA *pRoom; SOCIETY_DATA *soc; int following; char *t; char follownum[20]; char *hunting_string = NULL; vnum = fread_number (fp); room_num = fread_number (fp); if ((pMob = get_mob_index (vnum)) == NULL) { fprintf (stderr, "Attempted to load nonexistent mob number: %d.\n", vnum); return; } if ((pRoom = get_room_index (room_num)) == NULL) { fprintf (stderr, "Attempted to load mob into nonexistent room: %d.\n", room_num); return; } ch = create_mobile (pMob); ch->society = fread_number (fp); ch->hit = fread_number (fp); ch->max_hit = fread_number (fp); ch->move = fread_number (fp); ch->max_move = fread_number (fp); following = fread_number (fp); hunting_string = str_dup (fread_string(fp, NULL)); if (str_cmp (hunting_string, "none")) { check_fgt(ch); if (ch->fgt->hunting) free_string (ch->fgt->hunting); ch->fgt->hunting = t; } if (following > 0) { check_fgt (ch); sprintf (follownum, "%d", following); if (ch->fgt->hunting) free_string (ch->fgt->hunting); ch->fgt->hunting = str_dup (follownum); } char_to_room (ch, pRoom); if (ch->society && (soc = society_lookup (NULL, ch->society)) != NULL) { for (i = 0; i < NUM_CASTES; i++) { if (soc->caste[i] && ch->pIndexData->vnum >= soc->caste[i]->mob_start_vnum && ch->pIndexData->vnum < soc->caste[i]->mob_start_vnum + UMIN(soc->caste[i]->num_ranks, MAX_CASTE_RANKS)) { soc->caste[i]->curr_pop[ch->pIndexData->vnum - soc->caste[i]->mob_start_vnum]++; break; } } } for (;;) { char *word; word = feof (fp) ? "END" : fread_word (fp); if (!str_cmp ("END", word)) break; else if (!str_cmp (word, "AffectData")) { AFFECT_DATA *paf; if (affect_free == NULL) { paf = mem_alloc (sizeof (*paf)); } else { paf = affect_free; affect_free = affect_free->next; } paf->type = fread_number (fp); paf->duration = fread_number (fp); paf->modifier = fread_number (fp); paf->location = fread_number (fp); paf->aff[0] = fread_number(fp); paf->aff[1] = fread_number(fp); paf->aff[2] = fread_number(fp); paf->aff[3] = fread_number(fp); paf->next = ch->affected; ch->affected = paf; } else if (!str_cmp ("#OBJECT", word)) { fread_obj (ch, fp, 0); } else { fprintf (fp, "BAD WORD READ IN MOBILES.DAT: %s.\n", word); } } return; } SOCIETY_DATA* society_lookup (char *name, int vnum) { /* This may have to be hashed later on, but not likely as there will probably be very few socities made. */ SOCIETY_DATA *soc; for (soc = society_list; soc != NULL; soc = soc->next) { if (soc->vnum == vnum || !str_cmp (soc->name, name)) return soc; } return NULL; } void do_society (CHAR_DATA *ch, char *argy) { SOCIETY_DATA *soc; int num_castes, i, j; char buf[STD_LENGTH]; char arg1[SML_LENGTH]; int society_number = -1; char buf1[100]; DEFINE_COMMAND ("society", do_society, POSITION_DEAD, MAX_LEVEL, LOG_NORMAL, "This lists all of the societies in the game!") if (IS_MOB (ch)) return; argy = one_argy (argy, arg1); if (arg1[0] == '\0' || arg1 == "") { send_to_char ("Syntax: Society list, or Society <name> or Society <number>\n\r", ch); return; } if (!str_cmp (arg1, "list")) { for (soc = society_list; soc != NULL; soc = soc->next) { num_castes = 0; for (i = 0; i < NUM_CASTES; i++) { if (soc->caste[i]) num_castes++; } sprintf (buf, "[%d] %15s: Room Start: %6d Num Castes: %d\n\r", soc->vnum, soc->name, soc->room_start_vnum, num_castes); send_to_char (buf, ch); } return; } if (!str_cmp (arg1, "purge") && is_number (argy)) { int i = atoi(argy); SOCIETY_DATA *soc; if ((soc = society_lookup (NULL, i)) != NULL) { CHAR_DATA *rch, *rchn; for (j = 0; j < TOTAL_LIST -1; j++) { for (rch = char_list[j]; rch ; rch = rchn) { rchn = rch->next; if (IS_MOB (rch) && rch->society == i) { extract_char (rch, TRUE); } } } send_to_char ("Ok, society purged of mobs.\n\r", ch); return; } else { send_to_char ("Society purge <number>\n\r", ch); return; } } if (!str_cmp (arg1, "update") && LEVEL (ch) == MAX_LEVEL) { update_society (); send_to_char ("All societies updated once.\n\r", ch); return; } if (is_number (arg1)) society_number = atoi (arg1); if ((soc = society_lookup (arg1, society_number)) != NULL) { sprintf (buf, "[%d] %15s Flags: %d Room Start: %6d Num Rooms: %d\n\r", soc->vnum, soc->name, soc->flags, soc->room_start_vnum, soc->num_start_rooms); send_to_char (buf, ch); for (i = 0; i < NUM_CASTES; i++) { if (soc->caste[i]) { sprintf (buf, "[%d] %-12s Start: %d ", i, (soc->caste[i]->name ? soc->caste[i]->name : "No Name"), soc->caste[i]->mob_start_vnum); strcat (buf, "Adv (Cpop/Mpop):\n\r "); for (j = 0; j < UMIN (soc->caste[i]->num_ranks, MAX_CASTE_RANKS); j++) { sprintf (buf1, "%2d (\x1b[1;31m%2d\x1b[0;37m/\x1b[1;37m%2d\x1b[0;37m) ", soc->caste[i]->chance_to_advance[j], soc->caste[i]->curr_pop[j], soc->caste[i]->max_pop[j]); strcat (buf, buf1); } strcat (buf, "\n\r"); send_to_char (buf, ch); } } return; } send_to_char ("Syntax: Society list, or Society <name> or Society <number> or Society update\n\r", ch); return; } void update_society (void) { CHAR_DATA *rch; CHAR_DATA *rchn; SOCIETY_DATA *soc; SINGLE_OBJECT *obj; MOB_PROTOTYPE *pMob; ROOM_DATA *room; int room_num; int i, j; bool found = FALSE; int rank = -1; CASTE_DATA *cst; int num_raw; int total_pop = 0; bool top_in_castes; /* Update growth in societies and make them do things */ if (--pulse_society < 0) pulse_society = MOB_LIST; for (rch = char_list[pulse_society]; rch != NULL; rch = rchn) { rchn = rch->next; found = FALSE; if (IS_PLAYER(rch) || !rch->society || !rch->in_room || (soc = society_lookup (NULL, rch->society)) == NULL ) continue; /* Now pick the path of any child that has grown up. */ if (soc->caste[0] && rch->pIndexData->vnum == (soc->caste[0]->mob_start_vnum + soc->caste[0]->num_ranks - 1)) { for (i = 1; i < NUM_CASTES; i++) { if ((cst = soc->caste[i]) != NULL && number_percent () < cst->chance_to_advance[0] && ((pMob = get_mob_index (cst->mob_start_vnum)) != NULL) && cst->curr_pop[0] < cst->max_pop[0]) { CHAR_DATA *sch; sch = create_mobile (pMob); if (replace_mob (rch, cst->mob_start_vnum)) { cst->curr_pop[0]++; soc->caste[0]->curr_pop[soc->caste[0]->num_ranks -1]--; if (IS_SET (cst->flags, CASTE_BUILDER)) { SINGLE_OBJECT *hammer; SINGLE_OBJECT *anvil; hammer = create_object (get_obj_index(90017), 0); obj_to (hammer, rch); wear_obj (rch, hammer, TRUE); anvil = create_object (get_obj_index (90018), 0); obj_to (anvil, rch); } if (IS_SET (cst->flags, CASTE_GATHERER)) { SINGLE_OBJECT *pickaxe; pickaxe = create_object (get_obj_index (20), 0); obj_to (pickaxe, rch); wear_obj (rch, pickaxe, TRUE); } } break; } } } else { for (i = 0; i < NUM_CASTES; i++) { /* Advance in a caste.... */ if ((cst = soc->caste[i]) != NULL && (rank = (rch->pIndexData->vnum - cst->mob_start_vnum)) >= 0) { if (rank < (cst->num_ranks -1) && (number_percent () < cst->chance_to_advance[rank + 1]) && (cst->curr_pop[rank + 1] < cst->max_pop[rank + 1]) && (pMob = get_mob_index (rch->pIndexData->vnum + 1)) != NULL) { if (replace_mob (rch, rch->pIndexData->vnum + 1)) { cst->curr_pop[rank + 1]++; cst->curr_pop[rank]--; } break; } if (IS_SET (cst->flags, CASTE_GATHERER)) { if (number_range (1,3) == 2) do_mine (rch, ""); num_raw = 0; for (obj = rch->carrying; obj != NULL; obj = obj->next_content) if (obj->pIndexData->item_type == ITEM_RAW) num_raw++; if (num_raw > 20 && number_range (1,3) == 2 && !HUNTING (rch)) { CASTE_DATA *cstt; int lowvnum; int upvnum; for (i = 0; i < NUM_CASTES; i++) { if ((cstt = soc->caste[i]) != NULL && cstt != cst && IS_SET (cstt->flags, CASTE_BUILDER)) { lowvnum = cstt->mob_start_vnum; upvnum = cstt->mob_start_vnum + cstt->num_ranks -1; } } } } if (IS_SET (cst->flags, CASTE_BUILDER)) { send_to_char ("moo", rch); } } } } } for (soc = society_list; soc != NULL; soc = soc->next) { /* Check if the society was wiped out and possibly end it... */ if ((cst = soc->caste[0]) != NULL && number_percent () < cst->chance_to_advance[0] && cst->curr_pop[0] < cst->max_pop[0]) { CHAR_DATA *sch; room_num = soc->room_start_vnum + number_range (0, UMAX(0, soc->num_start_rooms)); if ((pMob = get_mob_index (cst->mob_start_vnum)) == NULL || ((room = get_room_index (room_num)) == NULL)) continue; sch = create_mobile (pMob); sch->society = soc->vnum; cst->curr_pop[0]++; char_to_room (sch, room); } total_pop = 0; top_in_castes = TRUE; for (i = 0; i < NUM_CASTES; i++) { if ((cst = soc->caste[i]) != NULL) { for (j = 0; j < cst->num_ranks; j++) { if (i > 0 && j == cst->num_ranks - 1 && cst->curr_pop[j] < cst->max_pop[j]) top_in_castes = FALSE; total_pop += cst->curr_pop[j]; } } } if (total_pop == 0 && soc->caste[0] && IS_SET (soc->flags, SOCIETY_DESTRUCTIBLE) && number_range(1,2) == 2) soc->caste[0]->max_pop[0] = 0; if (!top_in_castes) continue; room = NULL; if (IS_SET(soc->flags, SOCIETY_SPAWNING) && number_range (1,10) == 2) { for (i = 0; i < 10; i++) { if ((room = get_room_index (number_range(1,200000))) != NULL) break; } } else if (IS_SET (soc->flags, SOCIETY_EXPANDING) && number_range(1,10)) { AREA_DATA *ar, *oldarea, *newarea; ROOM_DATA *rid; int hash, door, num_adjacent_areas, area_chosen, choice; if ((rid = get_room_index(soc->room_start_vnum)) == NULL) continue; else oldarea = rid->area; for (ar = area_first; ar != NULL; ar = ar->next) REMOVE_BIT (ar->area_flags, AREA_TEMPFLAG); for (hash = 0; hash < HASH_MAX; hash = hash++) { for (rid = room_hash[hash]; room != NULL; room = room->next) { if (rid->area != oldarea) continue; for (door = 0; door < MAX_DIR; door++) { if (rid->exit[door] && rid->exit[door]->to_room) SET_BIT (rid->exit[door]->to_room->area->area_flags, AREA_TEMPFLAG); } } } num_adjacent_areas = 0; for (ar = area_first; ar != NULL; ar = ar->next) { if (IS_SET (ar->area_flags, AREA_TEMPFLAG)) num_adjacent_areas++; } if (num_adjacent_areas < 2) continue; else area_chosen = number_range(1,num_adjacent_areas); newarea = NULL; choice = 0; for (ar = area_first; ar != NULL; ar = ar->next) { if (IS_SET (ar->area_flags, AREA_TEMPFLAG)) { choice++; } if (choice == area_chosen) { newarea = ar; break; } } for (ar = area_first; ar != NULL; ar = ar->next) { REMOVE_BIT (ar->area_flags, AREA_TEMPFLAG); } if (newarea) { room = NULL; for (i = 0; i < 10; i++) { if ((room = get_room_index (number_range(newarea->lvnum, newarea->uvnum))) != NULL) break; } } } if (room) { SOCIETY_DATA *newsoc; bool caste_done[NUM_CASTES]; for (j = 0; j < NUM_CASTES; j++) caste_done[j] = FALSE; newsoc = new_society(); copy_society (soc, newsoc); newsoc->vnum = ++top_society; newsoc->flags |= SOCIETY_DESTRUCTIBLE; newsoc->room_start_vnum = room->vnum; for (rch = char_list[pulse_society]; rch != NULL; rch = rchn) { rchn = rch->next; if (IS_MOB (rch) && rch->society == soc->vnum) { for (j = 1; j < NUM_CASTES; j++) { if (newsoc->caste[j] && rch->pIndexData->vnum == soc->caste[j]->mob_start_vnum + soc->caste[j]->num_ranks -1) { if (number_range(1,5) == 2) { char_from_room (rch); char_to_room (rch, room); soc->caste[j]->curr_pop[soc->caste[j]->num_ranks -1]--; newsoc->caste[j]->curr_pop[newsoc->caste[j]->num_ranks -1]++; rch->society = newsoc->vnum; caste_done[j] = TRUE; } else if (number_range(1,2) == 2) { char_from_room(rch); extract_char (rch, TRUE); } } } } } } } save_society (); return; } bool replace_mob (CHAR_DATA *ch, int vnum) { int oldhp, oldmaxhp, oldmove, oldmaxmove, i; MOB_PROTOTYPE *pMob; if ((pMob = get_mob_index (vnum)) == NULL || !ch || IS_PLAYER (ch)) return FALSE; oldhp = ch->hit; oldmaxhp = ch->max_hit; if (oldmaxhp < 1) oldmaxhp = 1; oldmove = ch->move; oldmaxmove = ch->max_move; if (oldmaxmove < 1) oldmaxmove = 1; ch->pIndexData = pMob; for (i = 0; i < 4; i++) { ch->aff[i] |= pMob->aff[i]; } ch->max_hit = UMAX(10+10*ch->pIndexData->level, ch->pIndexData->level*ch->pIndexData->level * ch->pIndexData->level/1000); ch->max_hit += number_range(0, ch->max_hit/10); ch->max_move = 100 + (2+ IS_SET(ch->pIndexData->act, ACT_MOUNTABLE)*4)*ch->pIndexData->level; ch->max_move += number_range(0, ch->max_move/10); if (ch->max_move > 30000 || ch->max_move < 100) ch->max_move = number_range(200, 1200); ch->damroll = 2 + ch->max_hit / (number_range (36, 48)); ch->max_hit = (ch->max_hit * 10 * (pMob->hpmult > 1000 ? (pMob->hpmult % 1000) : pMob->hpmult)) / 100; if (ch->max_hit <= 1) { ch->max_hit = 10; } ch->hit = ch->max_hit * PERCENTAGE (oldhp, oldmaxhp)/100; ch->move = ch->max_move * PERCENTAGE (oldmove, oldmaxmove)/100; add_char_to_list (ch); return TRUE; } void do_sociedit (CHAR_DATA * ch, char *argy) { int value; SOCIETY_DATA *soc; DEFINE_COMMAND ("sociedit", do_sociedit, POSITION_DEAD, MAX_LEVEL, LOG_NORMAL, "The society editor: yay!") if (IS_MOB (ch)) return; if (!str_cmp (argy, "create")) { soc = new_society (); top_society++; soc->vnum = top_society; changed_societies = TRUE; ch->desc->pEdit = (void *) soc; ch->desc->connected = CON_SOCIEDITOR; show_society (ch, soc, -1); return; } if (is_number (argy)) value = atoi (argy); else value = -1; if ((soc = society_lookup ( (argy[0] ? argy : NULL), value)) != NULL) { ch->desc->pEdit = (void *) soc; ch->desc->connected = CON_SOCIEDITOR; show_society (ch, soc, -1); return; } send_to_char ("Syntax: SOCIEDIT <number>, SOCIEDIT <name>, SOCIEDIT CREATE.\n\r", ch); return; } void sociedit (CHAR_DATA *ch, char *argy) { char *oldarg = argy; CASTE_DATA *caste = NULL; char arg1[SML_LENGTH]; char arg2[SML_LENGTH]; char arg3[SML_LENGTH]; char arg4[SML_LENGTH]; char arg5[SML_LENGTH]; char buf[SML_LENGTH]; int value = 0; int value2 = 0; int caste_num = -1; SOCIETY_DATA *soc = (SOCIETY_DATA *) ch->desc->pEdit; if (!soc) { interpret (ch, argy); return; } arg1[0] = '\0'; arg2[0] = '\0'; argy = one_argy (argy, arg1); if (arg1[0] == '\0') { show_society (ch, soc, -1); return; } if (!str_cmp (arg1, "done")) { ch->desc->pEdit = NULL; ch->desc->connected = CON_PLAYING; sprintf (arg1, "\x1B[1;%dr\x1B[2J\x1B[%d;1f", ch->pcdata->pagelen, ch->pcdata->pagelen); send_to_char (arg1, ch); return; } if (!str_cmp ("name", arg1)) { if (argy[0] == '\0' || argy == "") { send_to_char ("Syntax: Name <string>\n\r", ch); return; } if (soc->name) { free_string (soc->name); } argy[0] = UPPER (argy[0]); soc->name = str_dup (argy); changed_societies = TRUE; show_society (ch, soc, 1); return; } argy = one_argy (argy, arg2); if (!str_cmp (arg1, "room_start")) { if (is_number (arg2)) value = atoi (arg2); else { send_to_char ("Syntax room_start <number>\n\r", ch); return; } soc->room_start_vnum = atoi (arg2); changed_societies = TRUE; show_society (ch, soc, 1); return; } if (!str_cmp (arg1, "num_rooms")) { if (is_number (arg2)) value = atoi (arg2); else { send_to_char ("Syntax num_rooms <number>\n\r", ch); return; } soc->num_start_rooms = atoi (arg2); changed_societies = TRUE; show_society (ch, soc, 1); return; } if (society_name_bit (arg1) != 0) { send_to_char ("Flag toggled\n\r", ch); TOGGLE_BIT (soc->flags, society_name_bit (arg1)); changed_societies = TRUE; show_society (ch, soc, 2); return; } if (!str_cmp (arg1, "caste")) { if (is_number (arg2) || atoi (arg2) < 0 || atoi (arg2) >= NUM_CASTES) caste_num = atoi(arg2); else { send_to_char ("Syntax caste <caste number> <what to change>.\n\r", ch); return; } if (!str_cmp (argy, "delete")) { if (!soc->caste[caste_num]) { send_to_char ("There was no caste there to delete.\n\r", ch); return; } if (soc->caste[caste_num]->name) free_string (soc->caste[caste_num]->name); free_m (soc->caste[caste_num]); soc->caste[caste_num] = NULL; send_to_char ("Ok, the caste was deleted.\n\r", ch); changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (!soc->caste[caste_num]) { soc->caste[caste_num] = new_caste (); changed_societies = TRUE; } caste = soc->caste[caste_num]; argy = one_argy (argy, arg3); argy = one_argy (argy, arg4); if (caste_name_bit (arg3) != 0) { send_to_char ("Caste flag toggled\n\r", ch); TOGGLE_BIT (caste->flags, caste_name_bit (arg3)); changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (is_number (arg4)) value = atoi (arg4); else value = -1; if (!str_cmp (arg3, "name")) { if (arg4[0] == '\0' || arg4 == "") { send_to_char ("Syntax Caste <number> name <Name of caste>.\n\r", ch); return; } if (caste->name) free_string (caste->name); arg4[0] = UPPER (arg4[0]); caste->name = str_dup (arg4); changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (!str_cmp (arg3, "ranks") || !str_cmp (arg3, "rank")) { if (value < 1 || value > MAX_CASTE_RANKS) { sprintf (buf, "The number of ranks must be a number between 1 and %d.\n\r", MAX_CASTE_RANKS); send_to_char (buf, ch); return; } caste->num_ranks = atoi (arg4); send_to_char ("The number of ranks is changed.\n\r", ch); changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (!str_cmp (arg3, "mobstart") || !str_cmp (arg3, "mob_start") || !str_cmp (arg3, "start_vnum")) { caste->mob_start_vnum = atoi (arg4); send_to_char ("The mob_vnum where this caste starts is changed.\n\r", ch); changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (!str_cmp (arg3, "maxpop") || !str_cmp (arg3, "max_pop")) { argy = one_argy (argy, arg5); if (is_number (arg5)) value2 = atoi (arg5); else value2 = -1; if (value < 0 || value2 < 0 || value > UMIN (MAX_CASTE_RANKS, caste->num_ranks) || value2 > 1000) { send_to_char ("Syntax: caste <caste_number> maxpop <rank_number> <value>\n\r", ch); return; } caste->max_pop[value] = value2; changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } if (!str_cmp (arg3, "adv_chance") || !str_cmp (arg3, "advance")) { argy = one_argy (argy, arg5); if (is_number (arg5)) value2 = atoi (arg5); else value2 = -1; if (value < 0 || value2 < 0 || value > UMIN (MAX_CASTE_RANKS - 1, caste->num_ranks - 1) || value2 > 1000) { send_to_char ("Syntax: caste <caste_number> advance <rank_number> <value>\n\r", ch); return; } caste->chance_to_advance[value] = value2; changed_societies = TRUE; show_society (ch, soc, 3 + caste_num); return; } } interpret (ch, oldarg); return; } void show_society (CHAR_DATA *ch, SOCIETY_DATA *soc, int row) { char buf[SML_LENGTH]; char buf1[100]; int i, j; if (!ch || !soc || IS_MOB (ch)) return; if (row == -1) { sprintf (buf, "\x1B[1;1f\x1B[K\x1B[2;1f\x1B[K\x1B[3;1f\x1B[K\x1B[4;1f\x1B[K\x1B[5;1f\x1B[K\x1B[6;1f\x1B[K\x1B[7;1f\x1B[K\x1B[8;1f\x1B[K\x1B[9;1f\x1B[K\x1B[10;1f\x1B[K\x1B[11;1f\x1B[K\x1B[12;1f\x1B[K\x1B[13;1f\x1B[K\x1B[14;%dr", ch->pcdata->pagelen); send_to_char (buf, ch); } if (row == -1 || row == 1) { send_to_char ("\x1B[1;1f\x1B[K", ch); sprintf (buf, "[%2d] %20s Room Start: %d Num Rooms: %d\n\r", soc->vnum, soc->name, soc->room_start_vnum, soc->num_start_rooms); send_to_char (buf, ch); } if (row == 2 || row == -1) { send_to_char ("\x1B[2;1f\x1B[K", ch); sprintf (buf, "Flags: %s\n\r", society_bit_name (soc->flags)); send_to_char (buf, ch); } for (i = 0; i < NUM_CASTES; i++) { if (row == 3 + i || row == -1) { sprintf (buf, "\x1b[%d;1f\x1b[K", 3 + i); send_to_char (buf, ch); if (!soc->caste[i]) { sprintf (buf, "[%d] No Caste.\n\r", i); send_to_char(buf, ch); } else { sprintf (buf, "[%d] %-12s Start: %d ", i, (soc->caste[i]->name ? soc->caste[i]->name : "No Name"), soc->caste[i]->mob_start_vnum); strcat (buf, "Adv(Mpop): "); for (j = 0; j < (UMIN (soc->caste[i]->num_ranks, MAX_CASTE_RANKS)); j++) { sprintf (buf1, "%2d(\x1b[1;37m%2d\x1b[0;37m)", soc->caste[i]->chance_to_advance[j], soc->caste[i]->max_pop[j]); strcat (buf, buf1); } } strcat (buf, "\n\r"); send_to_char (buf, ch); } } sprintf (buf, "\x1B[%d;1f", ch->pcdata->pagelen); send_to_char (buf, ch); return; } void update_area_control (void) { AREA_DATA *ar; int i; MOB_PROTOTYPE *mob; for (i = 0; i < NUM_ALIGN; i++) { areas_controlled[NUM_ALIGN] = 0; max_area_power[NUM_ALIGN] = 0; } raidable = 0; for (ar = area_first; ar != NULL; ar = ar->next) { ar->power = 0; if (IS_SET (ar->area_flags, AREA_RAIDABLE)) { if (ar->alignment >= 0 && ar->alignment < NUM_ALIGN) { areas_controlled[ar->alignment]++; } else { ar->alignment = 0; } raidable++; } } for (i = 0; i < HASH_MAX; i++) { for (mob = mob_index_hash[i]; mob; mob = mob->next) { mob->area->power += mob->level * mob->max_in_world; } } for (ar = area_first; ar; ar = ar->next) { if (ar->power > max_area_power[ar->alignment]) max_area_power[ar->alignment] = ar->power; } return; } void do_seize (CHAR_DATA * ch, char * argy) { SINGLE_OBJECT *token; MOB_PROTOTYPE *mob; int i; AREA_DATA *ar; bool any_alive = FALSE; DEFINE_COMMAND ("seize", do_seize, POSITION_STANDING, 0, LOG_ALWAYS, "This command allows you to seize a city for your alignment. You must be in the war room to do it.\n\r") if (IS_MOB (ch)) return; ar = ch->in_room->area; if (LEVEL (ch) < MAX_LEVEL) { if (ch->pcdata->alignment >= NUM_ALIGN || ch->pcdata->alignment < 1) { send_to_char ("Those of your alignment cannot seize control of a city!\n\r", ch); return; } if (!ch->in_room || ch->in_room->vnum != ch->in_room->area->lvnum) { send_to_char ("You must be in the war room to seize control of the city!\n\r", ch); return; } if (!IS_SET (ar->area_flags, AREA_RAIDABLE)) { send_to_char ("This area cannot be raided and seized!\n\r", ch); return; } for (token = ch->carrying; token != NULL; token = token->next_content) { if (token->pIndexData->vnum == WAR_TOKEN_VNUM) break; } if (!token) { send_to_char ("You must be holding a war token to seize control of a city.\n\r", ch); return; } for (i = 0; i < HASH_MAX && !any_alive; i++) { for (mob = mob_index_hash[i]; mob; mob = mob->next) { if (mob->vnum >= ar->lvnum && mob->vnum <= ar->uvnum && mob->count > 0) { any_alive = TRUE; break; } } } if (any_alive) { send_to_char ("You have failed to kill all of the creatures in this city!\n\r", ch); obj_from (token); free_it (token); return; } ar->lastkiller = ch->pcdata->online_spot; set_area_align (ar, ch->pcdata->alignment, ch); obj_from (token); free_it (token); return; } else { ar->lastkiller = ch->pcdata->online_spot; ar->area_flags |= AREA_RAIDABLE; if (is_number (argy) && atoi (argy) >= 0 && atoi (argy) < NUM_ALIGN) { set_area_align (ar, atoi(argy), ch); } else { set_area_align (ar, ch->pcdata->alignment, ch); } ar->lastkiller = NULL; send_to_char ("Ok, area alignment set.\n\r", ch); return; } return; } void set_area_align (AREA_DATA *ar, int align, CHAR_DATA *ch) { CHAR_DATA *sch; int i; MOB_PROTOTYPE *mob; char buf[STD_LENGTH]; if (!ar->lastkiller || align < 0 || align >= NUM_ALIGN) return; if (ar->alignment != align && (!ch || LEVEL (ch) < MAX_LEVEL)) { sch = create_mobile (get_mob_index(1)); char_to_room (sch, get_room_index(1)); sprintf (buf, "Hear Ye! Hear Ye! %s and the %s forces have conquered %s, and it is now closed to all not allied with them! Beware!\n\r", ar->lastkiller->name, align_info[ar->lastkiller->alignment].name, ar->name); do_echo (sch, buf); extract_char (sch, TRUE); } ar->alignment = align; for (i = 0; i < HASH_MAX; i++) { for (mob = mob_index_hash[i]; mob != NULL; mob = mob->next) { if (mob->vnum >= ar->lvnum && mob->vnum <= ar->uvnum) { mob->alignment = align; if (align > 0) { if (!ch || LEVEL(ch) < MAX_LEVEL) { mob->level += 5; } if (mob->guard && mob->guard->guarding_door) { SET_BIT (mob->act3, ACT3_GUARD_DOOR_ALIGN); REMOVE_BIT (mob->act3, ACT3_GUARD_DOOR); } SET_BIT (mob->act4, ACT4_KILL_OPP); REMOVE_BIT (mob->act, ACT_AGGRESSIVE | ACT_ANGRY); } else { REMOVE_BIT (mob->act4, ACT4_KILL_OPP); REMOVE_BIT (mob->act3, ACT3_GUARD_DOOR_ALIGN); } } } } SET_BIT (ar->area_flags, AREA_CHANGED); save_area_list (); save_area (ar); update_area_control (); return; } void do_control (CHAR_DATA * ch, char * argy) { int align = NUM_ALIGN; char buf[SML_LENGTH]; AREA_DATA *ar; int i; DEFINE_COMMAND ("control", do_control, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you see the state of the areas under the control of the various alignments.\n\r") update_area_control(); if (!str_cmp (argy, "full")) { sprintf (hugebuf_o, "All areas currently under control and who owns them:\n\n\r"); for (i = 0; i < NUM_ALIGN; i++) { sprintf (buf, "\n\n\r%s held cities:\n\n\r", align_info[i].name); strcat (hugebuf_o, buf); for (ar = area_first; ar != NULL; ar = ar->next) { if (IS_SET (ar->area_flags, AREA_RAIDABLE) && ar->alignment == i) { sprintf (buf, "%30s held by %s with power %d.\n\r", ar->name, align_info[ar->alignment].name, ar->power); strcat (hugebuf_o, buf); } } } page_to_char (hugebuf_o, ch); return; } for (i = 0; i < NUM_ALIGN; i++) { if (!str_cmp (argy, align_info[i].name)) { align = i; break; } } if (align != NUM_ALIGN) { do_areas (ch, align_info[i].name); return; } send_to_char ("This is the breakdown of the areas under control in the game:\n\r", ch); sprintf (buf, "\n\n\rNumber of raidable areas: %d\n\n\r", raidable); send_to_char (buf, ch); for (i = 0; i < NUM_ALIGN; i++) { sprintf (buf, "%s cities : %d Max Power: %d\n\r", align_info[i].name, areas_controlled[i], max_area_power[i]); send_to_char (buf, ch); } return; } void do_citymap (CHAR_DATA *ch, char *argy) { AREA_DATA *ar; int i; char *t; char area_name[SML_LENGTH]; DEFINE_COMMAND ("citymap", do_citymap, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you see a map of what the cities under alignment control look like.") bzero (outp, sizeof(outp)); bzero (colrs, sizeof(colrs)); for (ar = area_first; ar != NULL; ar = ar->next) { if (IS_SET (ar->area_flags, AREA_RAIDABLE) && ar->alignment >= 0 && ar->alignment < NUM_ALIGN) { outp[ar->x][ar->y -1] = '*'; colrs[ar->x][ar->y -1] = 8 + ar->alignment; strcpy (area_name, ar->name); t = area_name; if (!str_prefix ("The City of", area_name)) { while (*t && *t != 'f') t++; t++; t++; } else if (!str_prefix ("The ", area_name) || !str_prefix ("An ", area_name) || !str_prefix ("A ", area_name) || !str_prefix ("More ", area_name)) { while (*t && *t != ' ') t++; t++; } for (i = 0; i < 5; i++) { if ((ar->x + i + 1< 80) && outp[ar->x + i + 1][ar->y-1] == '\0') { if (*t) { colrs[ar->x + i + 1][ar->y-1] = 7; outp[ar->x + i + 1][ar->y-1] = *t; } t++; } } } } ch->pcdata->maxx = 80; ch->pcdata->maxy = 25; do_rawclear(ch); draw_data (ch, 25); return; }