/*************************************************************************** * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming * * License by Wizards of the Coast. All comments referring to D20, OGL, * * and SRD refer to the System Reference Document for the Open Gaming * * system. Any inclusion of these derivatives must include credit to the * * Mud20 system, the full and complete Open Gaming LIcense, and credit to * * the respective authors. See ../doc/srd.txt for more information. * * * * Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. * * * * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey * * * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. * ***************************************************************************/ #include "mud.h" /* bounty.c Scandum 20-05-2002 Modified to serve as area justice system by Kregor - 9-2011 */ char * const crime_titles [] = { "none", "thievery", "assault", "low murder", "high murder", "*" }; void send_bounty_message(char *message) { NOTE_DATA *pnote; FILE *fp; push_call("send_bounty_message(%p)",message); // disabling for now, maybe with a more robust message board - Kregor pop_call(); return; ALLOCMEM( pnote, NOTE_DATA, 1); pnote->next = NULL; pnote->sender = STRALLOC("Bounty Office"); pnote->date = STRALLOC(get_time_string(mud->current_time)); pnote->time = mud->current_time; pnote->to_list = STRALLOC("All"); pnote->subject = STRALLOC("New Contract!"); pnote->room_vnum = 30961; pnote->text = STRALLOC(message); LINK(pnote, mud->f_note, mud->l_note, next, prev); close_reserve(); fp = my_fopen (NOTE_FILE, "a",FALSE); if (fp == NULL) { perror (NOTE_FILE); } else { fprintf (fp, "Sender %s~\nDate %s~\nTime %ld\nTo %s~\nSubject %s~\nTopic %d\nText\n%s~\nRoom %u\n\n", pnote->sender, pnote->date, pnote->time, pnote->to_list, pnote->subject, pnote->topic, fixer(pnote->text), pnote->room_vnum); fflush (fp); } my_fclose(fp); open_reserve(); pop_call(); return; } /* * Get PC's criminal record for specified crime in an area. * Pass -1 for record of ANY crime in area - Kregor */ BOUNTY_DATA *get_record( CHAR_DATA *ch, AREA_DATA *area, int crime ) { BOUNTY_DATA *bounty; push_call("is_wanted(%p)",ch); if (IS_NPC(ch)) { pop_call(); return NULL; } for (bounty = mud->f_bounty ; bounty ; bounty = bounty->next) { if (bounty->pvnum == ch->pcdata->pvnum && bounty->area == area->low_r_vnum && (crime == -1 || bounty->crime == crime)) { pop_call(); return (bounty); } } pop_call(); return NULL; } /* * PC posting of bounties - Kregor */ void do_bounty( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; char buf[MAX_INPUT_LENGTH]; int amount = 0; int crime, count; CHAR_DATA *judge; CHAR_DATA *victim; BOUNTY_DATA *bounty; bool loaded = FALSE; push_call("do_bounty(%p,%p)",ch,argument); if (IS_NPC(ch)) { pop_call(); return; } /* make sure the judge for the area is present */ for (judge = ch->in_room->first_person ; judge ; judge = judge->next_in_room) { if (IS_NPC(judge) && judge->pIndexData->vnum == judge->in_room->area->judge) { break; } } if (judge == NULL) { send_to_char( "You must be with the local judge to do that.\n\r", ch ); pop_call(); return; } if (*argument == '\0') { send_to_char("Syntax: bounty <post|list|info|register> [amount] [target]\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if (!strcasecmp(arg, "post")) { argument = one_argument(argument, arg); amount = atoi(arg); if (amount <= 0) { send_to_char("You can't post a bounty with no money.\n\r", ch); pop_call(); return; } argument = one_argument(argument, arg); if ((victim = lookup_char(arg)) == NULL) { if ((victim = start_partial_load(ch, arg)) == NULL) { pop_call(); return; } loaded = TRUE; } if (IS_IMMORTAL(victim)) { send_to_char("You may not post bounties on Immortals.\n\r", ch); if (loaded) { clear_partial_load(victim); } pop_call(); return; } if (!IS_SET(victim->act, PLR_KILLER) && !IS_SET(victim->act, PLR_THIEF)) { command(judge, do_say, "%s has committed no crimes against you.", victim->name); if (loaded) { clear_partial_load(victim); } pop_call(); return; } if (IS_SET(victim->act, PLR_KILLER)) crime = CRIME_HIGH_MURDER; else if (IS_SET(victim->act, PLR_THIEF)) crime = CRIME_MUGGING; else crime = 0; if (amount < 10000 * crime * victim->level) { ch_printf_color(ch, "The minimum bounty is %s.\n\r", 10000 * victim->level); pop_call(); return; } if (!gold_transaction(ch, 0 - amount)) { do_say(judge, "You do not have that much gold."); if (loaded) { clear_partial_load(victim); } pop_call(); return; } post_bounty(ch, victim, amount, crime); save_bounties(); do_say(judge, "The bounty has been posted, and shall be noted."); // if (!IS_IMMORTAL(ch)) // { // bounty = get_bounty(victim->pcdata->pvnum); // // strftime(arg, 12, "%2e %b %Y", gmtime( (const time_t *) &bounty->expires)); // // sprintf(buf, "\n\r{078}A bounty of %s has been posted on %s's head by %s.\n\r", format_coins(bounty->amount,FALSE), victim->name, ch->name); // // send_bounty_message(buf); // } // if (loaded) { clear_partial_load(victim); } } else if (!strcasecmp(arg, "info")) { argument = one_argument(argument, arg); for (count = 0, bounty = mud->f_bounty ; bounty ; bounty = bounty->next) { if (bounty->area != judge->pIndexData->area->low_r_vnum) { continue; } count++; if (is_number(arg) && count == atoi(arg)) { break; } if (strcmp(bounty->name, arg)) { break; } } if (!bounty) { command(judge, do_say, "There is no bounty posted on '%s'.\n\r", arg); pop_call(); return; } if (bounty->expires < mud->current_time) { send_to_char("That bounty has expired.\n\r", ch); remove_bounty(bounty); save_bounties(); pop_call(); return; } if (bounty->victim) strcpy(arg, mob_index[bounty->victim]->short_descr); else if (bounty->pcvictim && is_string(pvnum_index[bounty->victim]->name)) strcpy(arg, pvnum_index[bounty->victim]->name); else { send_to_char("That bounty is invalid.\n\r", ch); remove_bounty(bounty); save_bounties(); pop_call(); return; } sprintf(buf, "%s is wanted for %s against %s.\n\r", bounty->name, crime_titles[bounty->crime], arg); if ((victim = get_char_pvnum(bounty->pvnum)) == NULL) { if ((victim = start_partial_load(ch, arg)) == NULL) { pop_call(); return; } loaded = TRUE; } if (victim) { cat_sprintf(buf, "A description of the quarry follows:\n\r%s,\n\r%s", adjective(victim), victim->description); } else { cat_sprintf(buf, "The criminal is described as %s.\n\r", adjective(victim)); cat_sprintf(buf, "There is no further description available.\n\r"); } if (loaded) { clear_partial_load(victim); } switch (bounty->punishment) { default: cat_sprintf(buf, "The wanted individual must be brought back ALIVE!\n\r"); break; case PUNISHMENT_SEVER: cat_sprintf(buf, "You must bring the HAND of %s to this office.\n\r", bounty->name); break; case PUNISHMENT_DEATH: cat_sprintf(buf, "You must present the HEAD of %s as proof of death!\n\r", bounty->name); break; } cat_sprintf(buf, "Expiration date for this bounty is: %s.\n\r", get_time_string(bounty->expires)); send_to_char_color(buf, ch); } else if (!strcasecmp(arg, "list")) { for (count = 0, bounty = mud->f_bounty ; bounty ; bounty = bounty->next) { if (bounty->area != judge->pIndexData->area->low_r_vnum) { continue; } count++; sprintf(arg, "%s, for %s", bounty->name, crime_titles[bounty->crime]); cat_sprintf(buf, " {178}%2d{200}] {178}%-36s %s\n\r", count, arg, format_coins(bounty->amount,FALSE)); } if (count == 0) { command(judge, do_sayto, "%s There are no outstanding bounties in %s.", ch->name, judge->pIndexData->area->name); pop_call(); return; } if (str_suffix("\n\r", buf)) { strncat(buf, "\n\r", MAX_STRING_LENGTH); } act( "$N shows you a list of the outstanding bounties in $t.", ch, judge->pIndexData->area->name, judge, TO_CHAR); act( "$N shows $n a list of the outstanding bounties in $t.", ch, judge->pIndexData->area->name, judge, TO_ROOM); send_to_char_color(buf, ch); pop_call(); return; } else { send_to_char("Syntax: bounty <post|list|info> [amount] [target]\n\r", ch); } pop_call(); return; } /* * Bounty posting for NPCs */ void set_bounty( CHAR_DATA *ch, CHAR_DATA *victim, int crime ) { int amt; push_call("do_bounty(%p,%p,%p)",ch,victim,crime); if (!IS_NPC(ch)) { pop_call(); return; } // NPC can only post bounty in his own area. if (ch->in_room->area != ch->pIndexData->area) { pop_call(); return; } if (IS_IMMORTAL(victim)) { pop_call(); return; } amt = crime * 10000 * victim->level; post_bounty(ch, victim, amt, crime); save_bounties(); // sprintf(buf, "\n\r{078}A bounty of %s has been posted on %s's head by %s of %s", // format_coins(amt,FALSE), victim->name, get_name(ch), ch->in_room->area->name); // cat_sprintf(buf, "\n\r{078}%s.\n\r", capitalize(adjective(victim))); // cat_sprintf(buf, "\n\r{078}The description of the wanted is as follows:\n\r"); // cat_sprintf(buf, victim->description); // // send_bounty_message(buf); // pop_call(); return; } void post_bounty(CHAR_DATA *ch, CHAR_DATA *victim, int amount, int crime) { BOUNTY_DATA *bounty; push_call("post_bounty(%p,%p,%p,%p)",ch,victim,amount,crime); if (IS_NPC(victim)) { pop_call(); return; } if (ch->in_room->area->punishment[crime] == PUNISHMENT_NOT_ENFORCED) { pop_call(); return; } if (IS_NPC(ch)) amount = crime * 10000 * victim->level; /* Increase the value of a current bounty */ for (bounty = mud->f_bounty ; bounty ; bounty = bounty->next) { if (bounty->pvnum == victim->pcdata->pvnum && bounty->crime == crime && bounty->area == ch->in_room->area->low_r_vnum) { bounty->amount = UMIN(1000000000, bounty->amount + amount); bounty->expires = mud->current_time + 2592000 + bounty->amount / 1000000 * 86400; bounty->victim = IS_NPC(ch) ? ch->pIndexData->vnum : 0; bounty->pcvictim = !IS_NPC(ch) ? ch->pcdata->pvnum : 0; pop_call(); return; } } ALLOCMEM(bounty, BOUNTY_DATA, 1); bounty->name = STRALLOC(capitalize(victim->name)); bounty->pvnum = victim->pcdata->pvnum; bounty->amount = amount; bounty->expires = mud->current_time + 2592000 + bounty->amount / 1000000 * 86400; bounty->area = ch->in_room->area->low_r_vnum; bounty->crime = crime; bounty->punishment = ch->in_room->area->punishment[crime]; bounty->victim = IS_NPC(ch) ? ch->pIndexData->vnum : 0; bounty->pcvictim = !IS_NPC(ch) ? ch->pcdata->pvnum : 0; sort_bounty(bounty); pop_call(); return; } void sort_bounty(BOUNTY_DATA *bounty) { BOUNTY_DATA *temp_bounty; push_call("sort_bounty(%p)",bounty); for (temp_bounty = mud->f_bounty ; temp_bounty ; temp_bounty = temp_bounty->next) { if (strcmp(bounty->name, temp_bounty->name) < 0) { INSERT_LEFT(bounty, temp_bounty, mud->f_bounty, next, prev); break; } } if (temp_bounty == NULL) { LINK(bounty, mud->f_bounty, mud->l_bounty, next, prev); } pop_call(); return; } void remove_bounty(BOUNTY_DATA *bounty) { push_call("remove_bounty(%p)",bounty); UNLINK(bounty, mud->f_bounty, mud->l_bounty, next, prev); STRFREE(bounty->name); FREEMEM(bounty); pop_call(); return; } BOUNTY_DATA *get_bounty( int pvnum ) { BOUNTY_DATA *bounty; push_call("get_bounty(%p)",pvnum); for (bounty = mud->f_bounty ; bounty ; bounty = bounty->next) { if (bounty->pvnum == pvnum) { pop_call(); return(bounty); } } pop_call(); return NULL; } bool collect_bounty( CHAR_DATA *ch, CHAR_DATA *victim ) { BOUNTY_DATA *bounty; AREA_DATA *area; OBJ_DATA *obj; char buf[MAX_INPUT_LENGTH]; push_call("collect_bounty(%p,%p)",ch,victim); if (IS_NPC(victim) || IS_NPC(ch)) { pop_call(); return FALSE; } if ((bounty = get_bounty(victim->pcdata->pvnum)) == NULL) { pop_call(); return FALSE; } if ((area = get_area_from_vnum(bounty->area)) == NULL) { remove_bounty(bounty); save_bounties(); pop_call(); return FALSE; } if (bounty->punishment == PUNISHMENT_DEATH) { act( "You sever $N's head to collect the bounty on it.", ch, NULL, victim, TO_CHAR); act( "$n severs $N's head as a grisly trophy.", ch, NULL, victim, TO_NOTVICT); obj = create_object(get_obj_index(OBJ_VNUM_BOUNTY_HEAD), 0); obj->level = victim->level; obj->cost = bounty->amount; obj->weight = victim->weight / 30; obj->owned_by = victim->pcdata->pvnum; sprintf(buf, "%s %s", obj->name, victim->name); RESTRING(obj->name, buf); sprintf(buf, "%s %s", obj->short_descr, get_name(victim)); RESTRING(obj->short_descr, buf); sprintf(buf, "The head of %s lies here.", get_name(victim)); RESTRING(obj->long_descr, buf); sprintf(buf, "The head of %s stares up at you, frozen in a permanent gasp of surprise.", get_name(victim)); RESTRING(obj->description, justify(buf, 80)); obj_to_char(obj, ch); } else if (bounty->punishment == PUNISHMENT_SEVER) { act( "You sever $N's hand to collect the bounty on it.", ch, NULL, victim, TO_CHAR); act( "$n severs $N's hand below the forearm.", ch, NULL, victim, TO_NOTVICT); obj = create_object(get_obj_index(OBJ_VNUM_BOUNTY_HEAD), 0); obj->level = victim->level; obj->cost = bounty->amount; obj->weight = 10; obj->owned_by = victim->pcdata->pvnum; sprintf(buf, "%s %s", obj->name, victim->name); RESTRING(obj->name, buf); sprintf(buf, "%s %s", obj->short_descr, get_name(victim)); RESTRING(obj->short_descr, buf); sprintf(buf, "The hand of someone lies here."); RESTRING(obj->long_descr, buf); sprintf(buf, "The hand is crudely cut off from the forearm as a grisly trophy."); RESTRING(obj->description, justify(buf, 80)); obj_to_char(obj, ch); } else if (victim->position == POS_DEAD || IS_PLR(victim, PLR_DEAD)) { act("You can no longer collect a bounty on $N, as $E is dead.", ch, NULL, victim, TO_CHAR); pop_call(); return FALSE; } else { int jailroom; if (!IS_AWAKE(victim)) { if (mob_index[area->guard] != NULL) { act("After $N's subdual, $t and a contingent come to drag $M to jail.", ch, mob_index[area->guard]->short_descr, victim, TO_ALL); } else { act("Mercenaries from $t come to drag $N away.", ch, area->name, victim, TO_ALL); } gold_transaction(ch, bounty->amount); act("You receive a bounty of $t.", ch, format_coins(bounty->amount, FALSE), NULL, TO_CHAR); remove_bounty(bounty); save_bounties(); // take the victim to jail. if ((jailroom = area->dungeon) == 0) { if ((jailroom = area->courtroom) == 0) { log_build_printf(bounty->area, "collect_bounty: dungeon and courtroom not set for area."); pop_call(); return TRUE; } } char_from_room(victim); char_to_room(victim, jailroom, TRUE); } } pop_call(); return TRUE; } bool confiscate( CHAR_DATA *ch, CHAR_DATA *victim ) { OBJ_DATA *obj; int vnum, pick, cnt; push_call("confiscate(%p,%p)",ch, victim); if ((vnum = ch->in_room->area->storeroom) == 0) { log_build_printf(ch->pIndexData->vnum, "No impound storeroom set for area."); pop_call(); return FALSE; } for (cnt = 0, obj = victim->first_carrying ; obj ; obj = obj->next_content) { if (IS_OBJ_TYPE(obj, ITEM_CONTAINER) || IS_OBJ_TYPE(obj, ITEM_SPELLPOUCH) || IS_OBJ_TYPE(obj, ITEM_SHEATH)) continue; if (IS_SET(obj->extra_flags, ITEM_CONCEALED)) continue; if (IS_OBJ_STAT(obj, ITEM_NODROP|ITEM_NOREMOVE|ITEM_INVENTORY)) continue; if (obj_cost(obj) < UMIN(victim->level * 5000, 100000)) continue; cnt++; } pick = number_range(1,cnt); for (cnt = 0, obj = victim->first_carrying ; obj ; obj = obj->next_content) { if (IS_OBJ_TYPE(obj, ITEM_CONTAINER) || IS_OBJ_TYPE(obj, ITEM_SPELLPOUCH) || IS_OBJ_TYPE(obj, ITEM_SHEATH)) continue; if (IS_SET(obj->extra_flags, ITEM_CONCEALED)) continue; if (IS_OBJ_STAT(obj, ITEM_NODROP|ITEM_NOREMOVE|ITEM_INVENTORY)) continue; if (obj_cost(obj) < UMIN(victim->level * 5000, 100000)) continue; if (pick == cnt) break; } if (!obj) { act("$n frisks you, but takes nothing.", ch, NULL, victim, TO_VICT); act("$n frisks $N, but takes nothing.", ch, NULL, victim, TO_NOTVICT); pop_call(); return FALSE; } if (IS_WORN(obj)) unequip_char(victim, obj, FALSE); obj_from_char(obj); obj->owned_by = victim->pcdata->pvnum; obj_to_room(obj, vnum); act("$n frisks you, and confiscates $p!", ch, obj, victim, TO_VICT); act("$n frisks $N, and confiscates $p!", ch, obj, victim, TO_NOTVICT); act("$n informs you to see the judge, and pay the fine, if you want it back.", ch, NULL, victim, TO_VICT); pop_call(); return TRUE; }