EXTRA_DESCR_DATA * AddED(OBJ_DATA * obj, char * keyword, char * data) { OBJ_INDEX_DATA * pObj; EXTRA_DESCR_DATA * ed; pObj = obj->pIndexData; ed = new_extra_descr(); ed->keyword = str_dup(keyword); ed->next = pObj->extra_descr; pObj->extra_descr = ed; ed->description = str_dup(data); return ed; }
void Forge::CompleteWeapon(CHAR_DATA & ch, ForgeContext & context) { // Determine the number of bonus points to spend bool forgeMaster(false); int bonusPoints(ch.level / 2); if (number_percent() <= get_skill(&ch, gsn_forgemaster)) { check_improve(&ch, NULL, gsn_forgemaster, true, 4); forgeMaster = true; bonusPoints += 10; } else check_improve(&ch, NULL, gsn_forgemaster, false, 4); if (ch.in_room != NULL && room_is_affected(ch.in_room, gsn_lavaforge)) bonusPoints += 20; if (context.named) bonusPoints += 60; bonusPoints -= context.flaws * 20; switch (Luck::Check(ch)) { case Luck::Lucky: bonusPoints += 5; break; case Luck::Unlucky: bonusPoints -= 5; break; default: break; } bonusPoints = UMAX(0, bonusPoints); // Build the special odds ranges from the weapon and base objects std::vector<std::pair<unsigned int, const SpecialInfo *> > specials; unsigned int nextIndex(0); for (SpecialMap::const_iterator iter(Specials().begin()); iter != Specials().end(); ++iter) { // Make sure there are sufficient points for at least 1 level of this special if (bonusPoints < iter->second.cost) continue; // Calculate odds unsigned int oddsRange(CalculateOddsRange(iter->second, context.weaponInfo->weapon, context.materials)); if (oddsRange == 0) continue; // Add in the range specials.push_back(std::make_pair(nextIndex, &iter->second)); nextIndex += oddsRange; } // Now choose the special types, up to three std::vector<const SpecialInfo *> chosenSpecials; if (nextIndex > 0) { for (size_t i(0); i < 3; ++i) { // Choose an index at random and find the associated special unsigned int index(number_range(0, nextIndex - 1)); for (size_t j(0); j + 1 < specials.size(); ++j) { if (specials[j].first <= index && specials[j + 1].first > index) { // Found the matching special, now verify that it is acceptable in the face of other chosen ones const SpecialInfo * chosenSpecial(specials[j].second); for (size_t k(0); k < chosenSpecials.size(); ++k) { // No duplicates and no more than one uniqueclass if (chosenSpecials[k] == chosenSpecial || (chosenSpecials[k]->uniqueClass && chosenSpecial->uniqueClass)) { chosenSpecial = NULL; break; } } if (chosenSpecial != NULL) chosenSpecials.push_back(chosenSpecial); break; } } } } // Create the base object OBJ_DATA * obj(create_object(get_obj_index(OBJ_VNUM_FORGEWEAPON), 0)); if (obj == NULL) { bug("Forge weapon failed due to bad obj creation", 0); send_to_char("An error has occurred, please contact the gods.\n", &ch); return; } // Fill out the basic info; use the first material as the object's material obj->level = ch.level; obj->weight = number_range(context.weaponInfo->minWeight, (context.weaponInfo->minWeight * 23) / 20); obj->weight = UMIN(obj->weight, context.weight); obj->size = context.weaponInfo->objSize; obj->cost = ((bonusPoints * bonusPoints) / 2) + number_range(0, 300); if (!context.materials.empty()) obj->material = context.materials[0]; if (!context.weaponInfo->damverbs.empty()) copy_string(obj->obj_str, context.weaponInfo->damverbs[number_range(0, context.weaponInfo->damverbs.size() - 1)].c_str()); obj->value[0] = context.weaponInfo->type; obj->value[1] = 10 + (ch.level / 10) + context.weaponInfo->dammod + (context.named ? 1 : 0); obj->value[2] = 2; obj->value[3] = context.weaponInfo->damtype; if (context.weaponInfo->twohanded) SET_BIT(obj->value[4], WEAPON_TWO_HANDS); // Now choose from the selected specials at random until out of points or possible specials while (bonusPoints > 0 && !chosenSpecials.empty()) { // Choose a special and add it in size_t index(number_range(0, chosenSpecials.size() - 1)); chosenSpecials[index]->callback(*obj); bonusPoints -= UMAX(1, chosenSpecials[index]->cost); // Remove the special if too costly for the remaining points or only one allowed if (bonusPoints < chosenSpecials[index]->cost || !chosenSpecials[index]->multipleAllowed) { chosenSpecials[index] = chosenSpecials[chosenSpecials.size() - 1]; chosenSpecials.pop_back(); } } // Compensate for bad luck with increased damage if (context.named && bonusPoints >= 10) ++obj->value[1]; // Choose an adjective from the set of common adjectives plus the weapon-specific adjectives WordList adjectives(Adjectives()); for (size_t i(0); i < context.weaponInfo->adjectives.size(); ++i) adjectives.push_back(context.weaponInfo->adjectives[i]); std::string adjective; if (!adjectives.empty()) adjective = adjectives[number_range(0, adjectives.size() - 1)]; // Break down the material set to only unique materials std::set<int> materials; for (size_t i(0); i < context.materials.size(); ++i) materials.insert(context.materials[i]); std::string materialAdjective; switch (materials.size()) { case 0: break; case 1: materialAdjective = material_table[context.materials[0]].name; break; case 2: { std::set<int>::iterator iter(materials.begin()); materialAdjective = material_table[*iter].name; materialAdjective += '-'; ++iter; materialAdjective += material_table[*iter].name; break; } default: materialAdjective = material_table[context.materials[0]].name; materialAdjective += "-alloyed"; break; } // Build the short desc std::ostringstream shortDesc; if (!adjective.empty()) shortDesc << adjective << ' '; if (!materialAdjective.empty()) shortDesc << materialAdjective << ' '; shortDesc << context.weaponInfo->name; std::string weaponShort(shortDesc.str()); if (!weaponShort.empty()) weaponShort = std::string(indefiniteArticleFor(weaponShort[0])) + ' ' + weaponShort; SetBasicDescs(*obj, weaponShort.c_str(), false); // Set up the exdesc std::ostringstream exdesc; switch (number_range(0, 2)) { case 0: exdesc << "Forged"; break; case 1: exdesc << "Formed"; break; default: exdesc << "Wrought"; break; } exdesc << " from "; switch (materials.size()) { case 0: exdesc << " pure metal"; break; case 1: exdesc << " pure " << material_table[context.materials[0]].name; break; case 2: { std::set<int>::iterator iter(materials.begin()); exdesc << "an alloy of " << material_table[*iter].name << " and "; ++iter; exdesc << material_table[*iter].name; break; } default: exdesc << " a metal alloy"; break; } exdesc << ", this "; if (!adjective.empty()) exdesc << adjective << ' '; exdesc << context.weaponInfo->name; if (IS_OBJ_STAT(obj, ITEM_GLOW)) exdesc << " gleams brightly."; else if (IS_OBJ_STAT(obj, ITEM_DARK)) exdesc << " seems to drink the light into its dark surface."; else if (IS_OBJ_STAT(obj, ITEM_HUM)) exdesc << " hums faintly."; else if (IS_OBJ_STAT(obj, ITEM_NODESTROY)) exdesc << " seems nearly indestructible."; else if (context.named) exdesc << " radiates an aura of power."; else if (forgeMaster) exdesc << " has been masterfully crafted."; else exdesc << " has been well-crafted."; exdesc << ' '; switch (number_range(0, 5)) { case 0: exdesc << "The bands of metal which comprise it have been folded over and over to toughen the final product."; break; case 1: exdesc << "Bands of metal flash-forged together serve to harden the weapon against wear."; break; case 2: exdesc << "Carved into the weapon's length are small straight-lined runes, etched with obvious care."; break; case 3: exdesc << "Folds of the metal have been beaten into the weapon's surface, reinforcing the craftsmanship."; break; case 4: exdesc << "Ornate filigree runs the length of the weapon, decorating it in gleaming metal."; break; default: exdesc << "The lines of the weapon are simple and unadorned, lending it a certain grim elegance."; break; } if (!context.weaponInfo->sentences.empty() && number_bits(1) == 0) exdesc << ' ' << context.weaponInfo->sentences[number_range(0, context.weaponInfo->sentences.size() - 1)]; if (TraitCount(*obj, Trait_Parry) > 0) exdesc << " Forged with unusual precision, the balance of this piece lends itself well to parrying blows."; if (TraitCount(*obj, Trait_Casting) > 0) exdesc << " A sense of focus permeates this piece, as though it has been well-prepared for the channeling of mystical energies."; switch (context.flaws) { case 0: switch (number_range(0, 3)) { case 0: exdesc << " The work is flawless, bearing no sign of weakness."; break; case 1: exdesc << " Clearly well-fashioned, this " << context.weaponInfo->name << " has been made to stand the test of time."; break; case 2: exdesc << " No trace of imperfection mars the surface of this beautiful " << context.weaponInfo->name << '.'; break; default: exdesc << " There is no sign of seam or solder, as though the weapon was cast as a single, perfect unit."; break; } break; case 1: switch (number_range(0, 2)) { case 0: exdesc << " A few minor imperfections mar the otherwise smooth surface of the " << context.weaponInfo->name << '.'; break; case 1: exdesc << " Though not immediately-visible, a couple of minor flaws are evident upon closer inspection."; break; default: exdesc << " Some dents remain from the original crafting, slightly weakening the metalwork."; break; } break; default: switch (number_range(0, 2)) { case 0: exdesc << " Significant flaws are evident along the " << context.weaponInfo->name << "'s length."; break; default: exdesc << " Several seams show clearly on the weapon's surface, evidence of clumsy forgework."; break; } break; } // Apply the desc exdesc << '\n'; EXTRA_DESCR_DATA * extraDesc(new_extra_descr()); copy_string(extraDesc->keyword, obj->name); copy_string(extraDesc->description, exdesc.str().c_str()); extraDesc->description = format_string(extraDesc->description); extraDesc->next = obj->extra_descr; obj->extra_descr = extraDesc; // Give the object to the char obj_to_char(obj, &ch); // Echoes (and charge max mana for the naming, if present) act("You quench the metalwork, now shaped into $p.", &ch, obj, NULL, TO_CHAR); act("$n quenches the metalwork, now shaped into $p.", &ch, obj, NULL, TO_ROOM); if (context.named) { act("You can feel the air about it charged with power drained from your very being, as the newly-forged weapon lies waiting to receive its true Name.", &ch, obj, NULL, TO_CHAR); ch.max_mana = UMAX(0, ch.max_mana - NamingManaCost); if (!IS_NPC(&ch)) ch.pcdata->perm_mana = UMAX(0, ch.pcdata->perm_mana - NamingManaCost); ch.mana = UMIN(ch.mana, ch.max_mana); // Add an effect to the char to indicate he can name the object AFFECT_DATA af = {0}; af.where = TO_AFFECTS; af.type = gsn_forgeweapon; af.location = APPLY_HIDE; af.duration = -1; af.point = obj; af.level = ch.level; affect_to_char(&ch, &af); } }
/* * Code to create rings for married people.... Used in do_marry to give * the newly weds their initial rings, but can be used by imms also to * reimburse lost rings (for whatever reason) * Usage: newring <char> * The ring will be given to char automatically. * This is part of the marriage code by Canth ([email protected]) * of Mythran */ void do_rings ( CHAR_DATA *ch, char *argument ) { CHAR_DATA *spouse1; CHAR_DATA *spouse2; char buf [ MAX_STRING_LENGTH ]; OBJ_DATA *ring; EXTRA_DESCR_DATA * ed; if ( !authorized( ch, "rings" ) ) return; if ( !(spouse1 = get_char_world( ch, argument ) ) || !(spouse2 = get_char_world( ch, spouse1->pcdata->spouse ) ) ) { send_to_char(C_DEFAULT, "They both need to be logged on to create the ring\n\r", ch ); return; } /* Ok, they're both logged on... Let's see what sex spous1 is, and give them appropriate ring, and string it properly */ switch( spouse1->sex ) { case SEX_FEMALE: { ring = create_object( get_obj_index( OBJ_VNUM_DIAMOND_RING ), 0 ); switch( spouse2->sex ) { case SEX_FEMALE: { sprintf( buf, "This is the beautiful diamond ring given to you by your lovely\n\rwife %s at your wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } case SEX_MALE: { sprintf( buf, "This is the beautiful diamond ring given to you by your handsome\n\rhusband %s at your wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } case SEX_NEUTRAL: default: { sprintf( buf, "This is the beautiful diamond ring given to you by your\n\rspouse %s at your wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } } ed = new_extra_descr(); ed->keyword = str_dup( "inscription" ); sprintf( buf, "The inscription reads:\n\rTo my lovely wife, yours forever, %s", spouse2->name ); ed->description = str_dup( buf ); ed->deleted = FALSE; ed->next = ring->extra_descr; ring->extra_descr = ed; break; } case SEX_MALE: case SEX_NEUTRAL: default: { ring = create_object( get_obj_index( OBJ_VNUM_WEDDING_BAND ), 0 ); switch( spouse2->sex ) { /* Description of the ring, depending on sex of spouse */ case SEX_FEMALE: { sprintf( buf, "This is the ring given to you by your beautifull wife %s\n\rat your wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } case SEX_MALE: { sprintf( buf, "This is the ring given to you by your handsome husband %s\n\rat your wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } case SEX_NEUTRAL: default: { sprintf( buf, "This is the ring given to you by your spouse %s at\n\ryour wedding. It signifies your eternal love for eachother.", spouse2->name ); ring->description = str_dup( buf ); break; } } /* Extra info for "look inscription" */ ed =new_extra_descr(); ed->keyword = str_dup( "inscription" ); ed->deleted = FALSE; ed->next = ring->extra_descr; ring->extra_descr = ed; switch( spouse1->sex ) { default: case SEX_MALE: { sprintf( buf, "The inscription reads:\n\rTo my handsome prince... Forever yours, %s", spouse2->name ); ed->description = str_dup( buf ); break; } case SEX_NEUTRAL: { sprintf( buf,"The inscription reads:\n\rForever love, %s", spouse2->name ); ed->description = str_dup( buf ); break; } } } } obj_to_char ( ring, spouse1 ); return; }
// Added by SinaC 2003 for Circle style void load_room_circle( FILE *fp ) { ROOM_INDEX_DATA *pRoomIndex; log_stringf(" ROOMS"); if ( area_last == NULL ) { bug( "Load_room_circle: no #AREA seen yet."); exit( 1 ); } for ( ; ; ) { int vnum; char letter; int door; int iHash; char *ln; int x1, x2, x3, x4, x5, x6; letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_room_circle: # not found."); exit( 1 ); } vnum = fread_number( fp ); if ( vnum == 0 ) break; fBootDb = FALSE; if ( get_room_index( vnum ) != NULL ) { bug( "Load_room_circle: vnum %d duplicated.", vnum ); exit( 1 ); } fBootDb = TRUE; // pRoomIndex = (ROOM_INDEX_DATA *) alloc_perm( sizeof(*pRoomIndex) ); pRoomIndex = new_room_index(); pRoomIndex->guild = 0; /* Not a guild */ pRoomIndex->owner = str_dup(""); pRoomIndex->people = NULL; pRoomIndex->contents = NULL; pRoomIndex->extra_descr = NULL; pRoomIndex->area = area_last; pRoomIndex->vnum = vnum; pRoomIndex->name = fread_string( fp ); pRoomIndex->description = fread_string( fp ); /* Area number */ fread_number( fp ); pRoomIndex->bstat(flags) = fread_flag_circle(fp); pRoomIndex->bstat(sector) = fread_number(fp); pRoomIndex->bstat(maxsize) = SIZE_NOSIZE; pRoomIndex->bstat(light) = 0; for ( door = 0; door < MAX_DIR; door++ ) // Modified by SinaC 2003 pRoomIndex->exit[door] = NULL; // Modified by SinaC 2003 /* defaults */ pRoomIndex->bstat(healrate) = 100; pRoomIndex->bstat(manarate) = 100; // Added by SinaC 2003 for mental user pRoomIndex->bstat(psprate) = 100; for ( ; ; ) { EXIT_DATA *pexit; int locks; EXTRA_DESCR_DATA *ed; letter = fread_letter( fp ); if ( letter == 'S' ) break; switch ( letter ) { case 'D' : door = fread_number( fp ); if ( door < 0 || door >= MAX_DIR ) { // Modified by SinaC 2003 bug( "Load_room_circle: vnum %d has bad door number.", vnum ); exit( 1 ); } if ( door == DIR_SPECIAL ) log_stringf("DIR_SPECIAL found for room vnum: %d.", vnum ); // pexit = (EXIT_DATA *) alloc_perm( sizeof(*pexit) ); pexit = new_exit(); pexit->description = fread_string( fp ); pexit->keyword = fread_string( fp ); pexit->exit_info = 0; pexit->rs_flags = 0; /* OLC */ locks = fread_number(fp); pexit->key = fread_number(fp); pexit->u1.vnum = fread_number(fp); pexit->orig_door = door; /* OLC */ switch ( locks ) { case 1: pexit->exit_info = pexit->rs_flags = EX_ISDOOR; break; case 2: pexit->exit_info = pexit->rs_flags = EX_ISDOOR | EX_PICKPROOF; break; default: pexit->exit_info = pexit->rs_flags = locks; break; } convert_exit_circle(pexit); // SinaC 2003 if ( IS_SET( pexit->exit_info, EX_CLIMB ) ) log_stringf("Room [%d], exit [%d] has CLIMB flag.", vnum, door ); pRoomIndex->exit[door] = pexit; pRoomIndex->old_exit[door] = pexit; break; case 'E' : // ed = (EXTRA_DESCR_DATA *) alloc_perm( sizeof(*ed) ); ed = new_extra_descr(); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); ed->next = pRoomIndex->extra_descr; pRoomIndex->extra_descr = ed; break; default : bug( "Load_room_circle: vnum %d has unknown flag.", vnum ); exit( 1 ); } } while (1) { letter = fread_letter( fp ); if ( letter == 'T' ) { // Script int scriptVnum = fread_number( fp ); char buf[MAX_STRING_LENGTH]; sprintf( buf, "room%d", scriptVnum ); pRoomIndex->program = hash_get_prog(buf); if (!pRoomIndex->program) bug("Can't find program for room vnum %d.", pRoomIndex->vnum); else { if ( get_root_class( pRoomIndex->program ) != default_room_class ) { bug("program for mob vnum %d is not a room program.", pRoomIndex->vnum); pRoomIndex->program = NULL; } else if ( pRoomIndex->program->isAbstract ) bug("program for room vnum %d is an ABSTRACT class.", pRoomIndex->vnum ); } } else { ungetc(letter,fp); break; } } convert_room_circle(pRoomIndex); iHash = vnum % MAX_KEY_HASH; pRoomIndex->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoomIndex; top_vnum_room = top_vnum_room < vnum ? vnum : top_vnum_room; /* OLC */ assign_area_vnum( vnum ); /* OLC */ } return; }
/* * Snarf an obj section. old style */ void load_obj_circle( FILE *fp ) { OBJ_INDEX_DATA *pObjIndex; char *word; log_stringf(" OBJECTS"); if ( !area_last ) { /* OLC */ bug( "Load_obj_circle: no #AREA seen yet."); exit( 1 ); } for ( ; ; ) { int vnum; char letter; int iHash; int x1, x2, x3, x4, x5, x6; letter = fread_letter( fp ); if ( letter != '#' ) { bug( "Load_obj_circle: # not found."); exit( 1 ); } vnum = fread_number( fp ); if ( vnum == 0 ) break; fBootDb = FALSE; if ( get_obj_index( vnum ) != NULL ) { bug( "Load_obj_circle: vnum %d duplicated.", vnum ); exit( 1 ); } fBootDb = TRUE; pObjIndex = new_obj_index(); pObjIndex->vnum = vnum; pObjIndex->area = area_last; /* OLC */ pObjIndex->new_format = FALSE; pObjIndex->reset_num = 0; newobjs++; pObjIndex->name = fread_string( fp ); pObjIndex->short_descr = fread_string_lower( fp ); pObjIndex->description = fread_string_upper( fp ); fread_string( fp ); // unused: action desc pObjIndex->material = 0; pObjIndex->item_type = fread_number( fp ); pObjIndex->extra_flags = fread_flag_circle( fp ); pObjIndex->wear_flags = fread_flag_circle( fp ); fread_flag_circle(fp); // unused ? pObjIndex->size = SIZE_NOSIZE; pObjIndex->value[0] = fread_number(fp); pObjIndex->value[1] = fread_number(fp); pObjIndex->value[2] = fread_number(fp); pObjIndex->value[3] = fread_number(fp); pObjIndex->weight = UMAX( 1, fread_number( fp ) ); pObjIndex->cost = fread_number( fp ); fread_number( fp ); // unused: rent/day fread_number(fp); // unused ? pObjIndex->condition = 100; pObjIndex->level = 1; for ( ; ; ) { letter = fread_letter( fp ); if ( letter == 'A' ) { AFFECT_DATA *paf; paf = new_affect(); createaff(*paf,-1,20,-1,0,AFFECT_INHERENT); addaff2(*paf,AFTO_CHAR,fread_number( fp ),AFOP_ADD,fread_number( fp )); //paf->where = AFTO_CHAR; //paf->op = AFOP_ADD; //paf->type = -1; //paf->level = 20; /* RT temp fix */ //paf->duration = -1; //paf->location = fread_number( fp ); //paf->modifier = fread_number( fp ); convert_af_circle( paf ); paf->next = pObjIndex->affected; pObjIndex->affected = paf; } else if ( letter == 'E' ) { EXTRA_DESCR_DATA *ed; // ed = (EXTRA_DESCR_DATA *) alloc_perm( sizeof(*ed) ); ed = new_extra_descr(); ed->keyword = fread_string( fp ); ed->description = fread_string( fp ); ed->next = pObjIndex->extra_descr; pObjIndex->extra_descr = ed; } else if ( letter == 'T' ) { // script int scriptVnum = fread_number( fp ); char buf[MAX_STRING_LENGTH]; sprintf( buf, "obj%d", scriptVnum ); pObjIndex->program = hash_get_prog(buf); if (!pObjIndex->program) bug("Can't find program for obj vnum %d.", pObjIndex->vnum); else { if ( get_root_class( pObjIndex->program ) != default_obj_class ) { bug("program for obj vnum %d is not a mob program." ,pObjIndex->vnum); pObjIndex->program = NULL; } else if ( pObjIndex->program->isAbstract ) bug("program for Obj vnum %d is an ABSTRACT class.", pObjIndex->vnum ); } } else { ungetc( letter, fp ); break; } } switch ( pObjIndex->item_type ) { case CIRCLE_ITEM_POTION: case CIRCLE_ITEM_SCROLL: pObjIndex->value[1] = slot_lookup( pObjIndex->value[1] ); pObjIndex->value[2] = slot_lookup( pObjIndex->value[2] ); pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] ); break; case CIRCLE_ITEM_STAFF: case CIRCLE_ITEM_WAND: pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] ); break; } convert_obj_circle( pObjIndex ); iHash = vnum % MAX_KEY_HASH; pObjIndex->next = obj_index_hash[iHash]; obj_index_hash[iHash] = pObjIndex; top_vnum_obj = top_vnum_obj < vnum ? vnum : top_vnum_obj; /* OLC */ assign_area_vnum( vnum ); /* OLC */ } return; }
void parse_sign( CHAR_DATA *ch, char *argument, int type ) { BUFFER *buffer; char buf[MAX_STRING_LENGTH]; char arg[MAX_INPUT_LENGTH]; OBJ_INDEX_DATA *pObjIndex; OBJ_DATA *obj; if ( IS_NPC(ch) ) return; argument = one_argument( argument, arg ); smash_tilde( argument ); if ( arg[0] == '\0' ) { return; } if ( !str_cmp( arg, "+" ) ) { sign_attach( ch,type ); if (ch->pnote->type != type) { send_to_char( "You already have a different note in progress.\n\r",ch); return; } if (strlen(ch->pnote->text)+strlen(argument) >= 4096) { send_to_char( "Sign too long.\n\r", ch ); return; } buffer = new_buf(); add_buf(buffer,ch->pnote->text); add_buf(buffer,argument); add_buf(buffer,"\n\r"); free_string( ch->pnote->text ); ch->pnote->text = str_dup( buf_string(buffer) ); free_buf(buffer); send_to_char( "Ok.\n\r", ch ); return; } if (!str_cmp(arg,"-")) { int len; bool found = FALSE; sign_attach(ch,type); if (ch->pnote->type != type) { send_to_char( "You already have a different note in progress.\n\r",ch); return; } if (ch->pnote->text == NULL || ch->pnote->text[0] == '\0') { send_to_char("No lines left to remove.\n\r",ch); return; } strcpy(buf,ch->pnote->text); for (len = strlen(buf); len > 0; len--) { if (buf[len] == '\r') { if (!found) /* back it up */ { if (len > 0) len--; found = TRUE; } else /* found the second one */ { buf[len + 1] = '\0'; free_string(ch->pnote->text); ch->pnote->text = str_dup(buf); return; } } } buf[0] = '\0'; free_string(ch->pnote->text); ch->pnote->text = str_dup(buf); return; } if ( !str_prefix( arg, "make" ) ) { sign_attach( ch,type ); if (ch->pnote->type != type) { send_to_char( "You already have a different note in progress.\n\r",ch); return; } free_string( ch->pnote->to_list ); free_string( ch->pnote->subject ); send_to_char( "Ok.\n\r", ch ); return; } if ( !str_prefix( arg, "clear" ) ) { if ( ch->pnote != NULL ) { free_note(ch->pnote); ch->pnote = NULL; } send_to_char( "Ok.\n\r", ch ); return; } if ( !str_prefix( arg, "show" ) ) { if ( ch->pnote == NULL ) { send_to_char( "You have no sign in progress.\n\r", ch ); return; } if (ch->pnote->type != type) { send_to_char("You aren't working on that kind of note.\n\r",ch); return; } send_to_char( ch->pnote->text, ch ); return; } if ( !str_prefix( arg, "post" ) || !str_prefix(arg, "send") || !str_prefix(arg, "save")) { EXTRA_DESCR_DATA *ed; if ( ch->pnote == NULL ) { send_to_char( "You have no sign in progress.\n\r", ch ); return; } if (ch->pnote->type != type) { send_to_char("You aren't working on that kind of note.\n\r",ch); return; } pObjIndex = get_obj_index(OBJ_VNUM_QUEST_SIGN); obj = create_object( pObjIndex, ch->level ); obj_to_room( obj, ch->in_room ); ed = new_extra_descr(); ed->keyword = str_dup( "sign" ); buffer = new_buf(); add_buf(buffer,ch->pnote->text); ed->description = str_dup(buf_string(buffer)); ed->next = NULL; obj->extra_descr = ed; ch->pnote = NULL; send_to_char( "A sign now floats before you.\n\r", ch ); return; } send_to_char( "You can't do that.\n\r", ch ); return; }