09 May, 2014, syn wrote in the 1st comment:
Votes: 0
Hey Folks,

Long time no see..

Anywho.

I am struggling mightily with this and I am sure I am being overly obtuse or blind.

Effectively what I am trying to do, and what partially works is:

Character receives a massive amount of data output (eg, a drop all)
Something detects this, and chokes off the output to the character (optionally providing a message).
The End.

I have fiddled with write_to_buffer, and have been able to get it to recognize an initial 'spam' burst. Great. I choke it off and send a message or take it on a date. Its golden.
Then, I get another amount of lines remaining past this choke point as further display.

It is irking me because then I have (output)spam message(output) and it just looks and feels disjointed to me. This happens moreso on a 'get all' than a 'drop all' I would assume due to the construction of both of those and how they are scanning/sending the data.

Depending on how i play with write_to_buffer I can increase or decrease the first amount of (output)msg(output) but I cant figure out how to simply call off the final burst.

If anyone is familiar with the codebase in general, or perhaps what I should look towards that would be greatly appreciated.

I have basically tried to do variations of the following:

if (d->outtop + length >= 32000)
{
char *cbuf;
d->outsize = 8000;
cbuf = alloc_mem( d->outsize );
d->outtop = 2000;
length = strlen(d->outsize);
strncpy(cbuf, d->outbuf, d->outsize);
free_mem(d->outbuf, d->outsize);
d->outbuf = cbuf;
write_to_buffer(d, "\n\r#0[#CS#cp#Ca#cm #RC#rh#Ro#rk#Re#0]#n\n\r",0);
bug("out",0);
//continue on to the rest of WTB
}
This equates to ouput kinda like this normally:

You drop a sword.
You drop a sword.
You drop a sword.
[Spam Choke]
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.
You drop a sword.

I imagine kind of what is going on is:

do blah -> act(blah to player) -> write_to_buffer(all this blah) -> oh no, spams! -> hey there was extra blah but its not enough to be spammy -> heres some spam and the rest of blah!

or, the act is sending data as a queue, and trickle filling the buffer in some way?

I am not savvy enough to know, i guess. Either way, I want to just kill the remainder after that choke. If I at the end, or just return on that, or settop = 0; etc I still get the follow on output, so I have to believe that its still being triggered. I just dont know what to do about it.

Again, any thoughts or advice would be appreciated.
09 May, 2014, syn wrote in the 2nd comment:
Votes: 0
wow sorry for the rest of the post being in code.. need more sleep..
09 May, 2014, syn wrote in the 3rd comment:
Votes: 0
also wow, what i posted was a failed attempt at clearing the outbuf memory to wipe it and see if that would work, which it didnt, and just crashed so..

what I have that works is:


if (d->outtop + length >= 32000)
{
d->outsize = 15999;
d->outbuf = alloc_mem( d->outsize );
d->outtop = 1000;
write_to_buffer(d, " Spam Choke\n\r", 0);
bug("outtop size",0);
}



Sorry.. really tired..
09 May, 2014, quixadhal wrote in the 4th comment:
Votes: 0
The simplest way is to have write_to_buffer() remember the last string it was given, and keep a counter… if the new string is the same as the remembered one, increment the counter. If the counter gets over a threshold, don't actually add the given line to the buffer. You'll want to reset the counter either when the string changes, or a reasonable amount of time passes (like a couple of seconds).

Also, not sure if your example display was the result of someone typing "drop sword" a bunch of times, or "drop all.sword"… if it was the latter, you should probably not just generate a line for each one, but condense that to "You drop 23 swords" or whatever… as part of the drop command.
09 May, 2014, syn wrote in the 5th comment:
Votes: 0
Hey now thats an idea.. I think i may run into a problem though where X dropped items may be different.

To make my example easier I was/am using a sword. But if that list of strings were 70% unique, I think I would still run into a similar issue. I could mostly resolve that by simply cutting out the source and make a general some/lots of items were taken/dropped. But I wanted a complete solution catching anything beyond that that may create a spam condition (mobs/or whatever else someone could come up with).

So, if I can truncate like messages thatd be ok, mainly, I just wanted to clear the rest of any output in that type of condition, but I suppose that may be hard given that it could come from any number of sources, and without some way to marker the data, write_to_buffer cant just 'know' this is the tail end of spam i guess.

As for that output above.. its the result of a drop all, this is pretty standard for the line of codebases as far as data output. So is/was disconnecting a player if they received to much spam as output.. I agree that it could/should be condensed, I wanted to but that would only help a couple subsets of the main 'issue' as it were.

Regardless.. I think i can pull that off so at least all of X repeated string beyond Y is stopped.
09 May, 2014, quixadhal wrote in the 6th comment:
Votes: 0
Hmmm, Ok. My old DikuMUD combines identical items (same vnum) in most aspects of displaying it to the player, so you'd see sword [20] or whatever in your inventory, and I think you'd see "You drop sword [20]" as well.

Good luck!
09 May, 2014, syn wrote in the 7th comment:
Votes: 0
Yeah unfortunately it loops through things like this, as i (re)discovered:

get all ->
is there a room? yes
can they see in this room? yes
can I see in this room? yes
are there objects? yes
finally lets start with object 1
get_obj
can they see me? yes
am i in something? no
can i be taken? yes
do I have a trigger? no
great! act(You pick up a Sword.) -> write to buffer
ok next object! get_obj
checks
great! next obj
rinse repeat until done scanning room.

So each object becomes an individual get action, and is sent 1 by 1 by 1 by 1, until done..

I am trying to think of how to do as you sort of suggested and even add a counter in that space, but I am having trouble globally setting the int, then comparing. I came up with a few mechanisms which seemed like they should work but just segfaulted so clearly that didnt work heh. More learning to do!
09 May, 2014, syn wrote in the 8th comment:
Votes: 0
Oh and thanks for the advice, it actually has me thinking in some different directions that once I learn more will be fruitful I think
09 May, 2014, Skol wrote in the 9th comment:
Votes: 0
Feel free to take and mod this to your needs, you'll probably just rip out the item type parts unless you have custom 'drops' for those.

- Dave.

else
{
/* 'drop all' or 'drop all.obj' */
// OK, let's do this like 'Drops quite a few items'
// With a random chance to notice a few of them?
// IE Joe drops a lot of items, you notice an arrow, a dagger, and many more.
// IE Joe puts a lot of items into the pit, you spot an apple, and much more.
found = FALSE;
int amount_drop = 0; // anti-spam
int item_dropped = 0; // pre-count
// Let's count how many first, then do the full one once we know that.
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;

if ((arg[3] == '\0' || is_name (&arg[4], obj->name))
&& can_see_obj (ch, obj)
&& obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
found = TRUE;
item_dropped ++; // one more.
}
}
char buf[256];
/* sprintf (buf, "Total items was %d.\r\n", item_dropped);
send_to_char (buf, ch);*/

for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;

if ((arg[3] == '\0' || is_name (&arg[4], obj->name))
&& can_see_obj (ch, obj)
&& obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
found = TRUE;
amount_drop ++; // one more.

obj_from_char (obj);
if (IS_OBJ_STAT (obj, ITEM_MELT_DROP))
{
if (amount_drop < 2)
{
act ("$n drops $p, which dissolves into smoke.", ch, obj, NULL, TO_ROOM_SEE);
act ("You drop $p, which dissolves into smoke.", ch, obj, NULL, TO_CHAR);
}
extract_obj (obj);
}
else
{
to_room = obj_drop_to_room (obj, ch->in_room);
if (ch->in_room == to_room)
{
if (amount_drop < 2)
{
act ("$n drops $p.", ch, obj, NULL, TO_ROOM_SEE);
act ("You hear something hit the floor.", ch, NULL, NULL, TO_ROOM_HEAR_ONLY);
act ("You drop $p.", ch, obj, NULL, TO_CHAR);
}

if (obj->item_type == ITEM_FISH)
{
if (to_room->sector_type == SECT_WATER_SWIM
|| to_room->sector_type == SECT_WATER_NOSWIM
|| to_room->sector_type == SECT_UNDERWATER
|| to_room->fpool != NULL)
{
//fish splash or sink if dead
if (obj->timer > 0 && obj->timer < 25) // dead fish
act ("$p hits the water and sinks out of sight.", ch, obj, NULL, TO_ALL);
else // live fish, swim off
act ("$p hits the water and swims away!", ch, obj, NULL, TO_ALL);
extract_obj (obj);
}
else
{
switch (to_room->sector_type)
{
default:
case SECT_INSIDE:
if (obj->timer > 0 && obj->timer < 25) // dead fish
act ("$p hits the floor with a splat.", ch, obj, NULL, TO_ALL);
else // live fish, swim off
act ("$p hits the floor and flops around for a bit.", ch, obj, NULL, TO_ALL);
break;
case SECT_CITY:
case SECT_FIELD:
case SECT_FOREST:
case SECT_HILLS:
case SECT_MOUNTAIN:
if (obj->timer > 0 && obj->timer < 25) // dead fish
act ("$p hits the ground with a splat.", ch, obj, NULL, TO_ALL);
else // live fish, swim off
act ("$p hits the ground and flops around for a bit.", ch, obj, NULL, TO_ALL);
break;
case SECT_DESERT:
if (obj->timer > 0 && obj->timer < 25) // dead fish
act ("$p hits the sand with a dull thud.", ch, obj, NULL, TO_ALL);
else // live fish, swim off
act ("$p hits the sand and flops around painfully.", ch, obj, NULL, TO_ALL);
break;
}
}
}

if (obj->item_type == ITEM_DICE)
{
obj->value[1] = number_range (1, obj->value[0]);
diceroll(ch, obj);
}

}
else
{
/* Check to see if it floated up. */
if ((ch->in_room->sector_type == SECT_UNDERWATER)
&& ((obj->materials.major == MAT_WOOD)
|| (obj->materials.major == MAT_CORK)))
{
if (amount_drop < 2)
{
act ("$n lets go of $p, which floats from sight above you.",
ch, obj, NULL, TO_ROOM_SEE);
act ("You let go of $p, which floats from sight above you.",
ch, obj, NULL, TO_CHAR);

for (vch = char_list; vch; vch = vch->next)
if (vch->in_room == to_room)
act ("$p floats up from below!", vch, obj, NULL, TO_CHAR);
}
}
else /* It fell or sank. */
{
if (amount_drop < 2)
{
act("$n drops $p, which vanishes from sight below you.",
ch, obj, NULL, TO_ROOM_SEE);
act("You drop $p, which vanishes from sight below you.",
ch, obj, NULL, TO_CHAR);

for (vch = char_list; vch; vch = vch->next)
if (vch->in_room == to_room)
act ("$p falls from the sky!", vch, obj, NULL, TO_CHAR);
}
}

}
if (obj)
{
if (HAS_TRIGGER_OBJ (obj, TRIG_DROP))
p_give_trigger (NULL, obj, NULL, ch, obj, TRIG_DROP);
if (HAS_TRIGGER_ROOM (ch->in_room, TRIG_DROP))
p_give_trigger (NULL, NULL, to_room, ch, obj, TRIG_DROP);
}
}
}
}
if (amount_drop > 1)
{
int quant = amount_drop -1;
sprintf (buf, "Along with %s more thing%s.", quant == 1 ? "one" : quant < 3 ? "a couple" : quant < 5 ? "a few" : quant < 10 ? "some" : quant < 50 ? "a lot" : quant < 100 ? "a ton" : "more things than Tasslehoff has and some", quant == 1 ? "" : "s");
act (buf, ch, obj, NULL, TO_CHAR);
act (buf, ch, NULL, NULL, TO_ROOM);
}
09 May, 2014, Skol wrote in the 10th comment:
Votes: 0
Ps. That was the else part vs 'drop X' or 'drop all' that's the all part, not sure what your code looks like.
09 May, 2014, syn wrote in the 11th comment:
Votes: 0
This is exactly what i was trying to do.. looking at that i was sooo close but way over thinking it.. wow, thank you so much! I really really appreciate it!
09 May, 2014, Skol wrote in the 12th comment:
Votes: 0
Glad to help :), strip out the junk you don't need btw heh.
19 May, 2014, syn wrote in the 13th comment:
Votes: 0
I know its been a while now since posting but I wanted to let you know I got it plugged in and works great. Some of the flags actually gave me a few new ideas to implement that i hadnt thought of.. specifically if your blind, but not deaf, you would certainly hear a bunch of stuff hitting the deck.. so thanks for the ideas as well!

Here is what I ended up with, will add ye to credits as well:

/* 'drop all' or 'drop all.obj' */
//The following is from Skol of Ansalon MUD
// OK, let's do this like 'Drops quite a few items'
// With a random chance to notice a few of them?
// IE Joe drops a lot of items, you notice an arrow, a dagger, and many more.
// IE Joe puts a lot of items into the pit, you spot an apple, and much more.
found = FALSE;
int amount_drop = 0; // anti-spam
int item_dropped = 0; // pre-count
// Let's count how many first, then do the full one once we know that.
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
if ((arg[3] == '\0' || is_name (&arg[4], obj->name))
&& can_see_obj (ch, obj)
&& obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
found = TRUE;
item_dropped ++; // one more.
}
}
char buf[256];
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
if ((arg[3] == '\0' || is_name (&arg[4], obj->name))
&& can_see_obj (ch, obj)
&& obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
found = TRUE;
amount_drop ++; // one more.
obj_from_char (obj);
if (IS_OBJ_STAT (obj, ITEM_VANISH))
{
if (amount_drop < 2)
{
act ("$n drops $p, which dissolves into smoke.", ch, obj, NULL, TO_ROOM);
act ("You drop $p, which dissolves into smoke.", ch, obj, NULL, TO_CHAR);
}
extract_obj (obj);
}
else
{
int to_room;
to_room = bobj_to_room(obj, ch->in_room);
if(to_room == 1)
{
if (amount_drop < 2)
{
act ("$n drops $p.", ch, obj, NULL, TO_ROOM);
//act ("You hear something hit the floor.", ch, NULL, NULL, TO_ROOM);
act ("You drop $p.", ch, obj, NULL, TO_CHAR);
}
}
if (obj)
{
if (HAS_TRIGGER_OBJ (obj, TRIG_DROP))
p_give_trigger (NULL, obj, NULL, ch, obj, TRIG_DROP);
if (HAS_TRIGGER_ROOM (ch->in_room, TRIG_DROP))
p_give_trigger (NULL, NULL, ch->in_room, ch, obj, TRIG_DROP);
}
}
}
}
if (amount_drop > 1)
{
int quant = amount_drop -1;
sprintf (buf, "Along with %s more thing%s.", quant == 1 ? "one" : quant < 3 ? "a couple" : quant < 5 ? "a few" : quant < 10 ? "some" : quant < 50 ? "a lot" : quant < 100 ? "a ton" : "things than you can count.. spammer.", quant == 1 ? "" : "s");
act (buf, ch, obj, NULL, TO_CHAR);
act (buf, ch, NULL, NULL, TO_ROOM);
}


I wasn't able to use obj_to_room as you had, so I created a new bool bobj_to_room that returns 1 on success, 0 on null/failure for the ro_room check. Did the trick quite nicely.

Again, many thanks!
20 May, 2014, Kaz wrote in the 14th comment:
Votes: 0
You would do yourself a great service by breaking the function down into smaller sub-functions.
21 May, 2014, syn wrote in the 15th comment:
Votes: 0
Yeah but see, thats forethought and planning, and would allow me to insert just a small tidbit in get/drop/put.

Your silly.

But yes, correct, I wanted to make sure I could make it work first.

Here is the final final, with the bits for drop only to make it contiguous

inside do_drop - replacing the entirety of what I posted above:

/* 'drop all' or 'drop all.obj' */
// modified Skol's code into various pieces to make maintenance/addition easier
// we now call mggdp_processor for any multi get give drop put obj command and let it do the actual work
// we will just keep count of it had a hit, or not.
found = FALSE; // preset false condition

char buf[256];
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
i = mggdp_processor(ch, obj, arg[3], arg[4], 1, dc);
if( i == 1 )
{
found = TRUE;
dc++;
}
}
}

if ( dc > 1)
{
mosm_message(ch, obj, dc);
}


mggdp_processor:
int mggdp_processor(CHAR_DATA *ch, OBJ_DATA *obj, char *arg1, char *arg2, int *type, int *dc)
{

if(type == 1)//drop
{
if ((arg1 == '\0' || is_name (arg2, obj->name)) && can_see_obj (ch, obj) && obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
obj_from_char (obj);
if (IS_OBJ_STAT (obj, ITEM_VANISH))
{
if (dc < 1)
{
act ("$n drops $p, which dissolves into smoke.", ch, obj, NULL, TO_ROOM);
act ("You drop $p, which dissolves into smoke.", ch, obj, NULL, TO_CHAR);
}
extract_obj (obj);
}
else
{
int to_room;
to_room = bobj_to_room(obj, ch->in_room);
if(to_room == 1)
{
if (dc < 1)
{
act ("$n #0drops#n $p#0.#n", ch, obj, NULL, TO_ROOM);
act ("#0You drop #n$p#0.#n", ch, obj, NULL, TO_CHAR);
}
}
if (obj)
{
if (HAS_TRIGGER_OBJ (obj, TRIG_DROP))
p_give_trigger (NULL, obj, NULL, ch, obj, TRIG_DROP);
if (HAS_TRIGGER_ROOM (ch->in_room, TRIG_DROP))
p_give_trigger (NULL, NULL, ch->in_room, ch, obj, TRIG_DROP);
}
}
return 1;
}
return 0;
}


mosm_message:
void mosm_message(CHAR_DATA *ch, OBJ_DATA *obj, int *dc)
{
char mbuf[256];
int i = 0;
int q = dc -1;

// set up some ranges!
if( q <= 1 )
i = 1;
else if( q < 10 )
i = 2;
else if( q < 25 )
i = 3;
else if( q < 50 )
i = 4;
else if( q > 50 )
i = 5;

if( i == 0 ) //we got passed some bad joojoo
return;

// lets make this a bit easier to maintain - for me
switch (i)
{
case 1:
sprintf(mbuf, "#0And one more object.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 2:
sprintf(mbuf, "#0And a few other things.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 3:
sprintf(mbuf, "#0Along with quite a few more items.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 4:
case 5:
sprintf(mbuf, "#0Along with more things than you can count.. #RS#rp#Ra#rm#Rm#re#Rr#r!#R!#0.. #n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
}
}


Thank you one and all for the help!
21 May, 2014, quixadhal wrote in the 16th comment:
Votes: 0
While we're nitpicking…. you really should get used to indenting your code consistently, if not as you're typing it in, then at least via a tool or your editor. If you had, you'd have noticed an extra closing brace in that first chunk right away. :)

In vim, you can highlight a block of text andhit = to indent it according to the rules of whatever language is active (C).

/* 'drop all' or 'drop all.obj' */
// modified Skol's code into various pieces to make maintenance/addition easier
// we now call mggdp_processor for any multi get give drop put obj command and let it do the actual work
// we will just keep count of it had a hit, or not.
found = FALSE; // preset false condition
char buf[256];
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
i = mggdp_processor(ch, obj, arg[3], arg[4], 1, dc);
if( i == 1 )
{
found = TRUE;
dc++;
}
}
} // <– no matching open brace…
if ( dc > 1)
{
mosm_message(ch, obj, dc);
}

int mggdp_processor(CHAR_DATA *ch, OBJ_DATA *obj, char *arg1, char *arg2, int *type, int *dc)
{
if(type == 1)//drop
{
if ((arg1 == '\0' || is_name (arg2, obj->name)) && can_see_obj (ch, obj) && obj->wear_loc == WEAR_NONE && can_drop_obj (ch, obj))
{
obj_from_char (obj);
if (IS_OBJ_STAT (obj, ITEM_VANISH))
{
if (dc < 1)
{
act ("$n drops $p, which dissolves into smoke.", ch, obj, NULL, TO_ROOM);
act ("You drop $p, which dissolves into smoke.", ch, obj, NULL, TO_CHAR);
}
extract_obj (obj);
}
else
{
int to_room;
to_room = bobj_to_room(obj, ch->in_room);
if(to_room == 1)
{
if (dc < 1)
{
act ("$n #0drops#n $p#0.#n", ch, obj, NULL, TO_ROOM);
act ("#0You drop #n$p#0.#n", ch, obj, NULL, TO_CHAR);
}
}
if (obj)
{
if (HAS_TRIGGER_OBJ (obj, TRIG_DROP))
p_give_trigger (NULL, obj, NULL, ch, obj, TRIG_DROP);
if (HAS_TRIGGER_ROOM (ch->in_room, TRIG_DROP))
p_give_trigger (NULL, NULL, ch->in_room, ch, obj, TRIG_DROP);
}
}
return 1;
}
return 0;
}
// …
} // <– added missing closing brace that would have been further down

void mosm_message(CHAR_DATA *ch, OBJ_DATA *obj, int *dc)
{
char mbuf[256];
int i = 0;
int q = dc -1;
// set up some ranges!
if( q <= 1 )
i = 1;
else if( q < 10 )
i = 2;
else if( q < 25 )
i = 3;
else if( q < 50 )
i = 4;
else if( q > 50 )
i = 5;
if( i == 0 ) //we got passed some bad joojoo
return;
// lets make this a bit easier to maintain - for me
switch (i)
{
case 1:
sprintf(mbuf, "#0And one more object.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 2:
sprintf(mbuf, "#0And a few other things.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 3:
sprintf(mbuf, "#0Along with quite a few more items.#n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
case 4:
case 5:
sprintf(mbuf, "#0Along with more things than you can count.. #RS#rp#Ra#rm#Rm#re#Rr#r!#R!#0.. #n");
act (mbuf, ch, obj, NULL, TO_CHAR);
act (mbuf, ch, NULL, NULL, TO_ROOM);
break;
}
}


In your mosm_message() function, you have a fencpost error. You have a condition for q < 50 and another for q > 50, but none for q == 50. Either one should be <= or the other should be >=. The other error is a logical one… You have a check to return if i == 0, but that can't ever happen unless q happens to equal 50 (with the unfixed code)… if q <= 0, i would be set to 1, and if q > 50 i would be set to 5. Presumably, you meant to trap negative or 0 values?

Hmmmm, I just noticed you're passing dc in as a pointer, but you're using it as if it were an integer. That will probably not work as you expect it to. If you really want to pass it as a pointer, you have to dereference it via *dc inside the function and pass the plain int in as &dc where it's called. But you probably don't want to do that… you most likely just want to declare it as a plain int.

I would probably have written it like this, and I would have killed you for using obnoxious color codes. *grin*

/*
* Emits a message based on the number of repetitions of the same object.
* dc is the duplicate count value, 0 meaning not duplicated.
*/
void mosm_message( CHAR_DATA *ch, OBJ_DATA *obj, int dc )
{
int i = 0;
const char **msgs[5] = {
"#0And one more object.#n",
"#0And a few other things.#n",
"#0Along with quite a few more items.#n",
"#0Along with more things than you can count.. #RS#rp#Ra#rm#Rm#re#Rr#r!#R!#0.. #n",
"#0Along with more things than you can count.. #RS#rp#Ra#rm#Rm#re#Rr#r!#R!#0.. #n"
};

if( dc <= 0) return;

if( dc > 1 ) i++;
if( dc > 10) i++;
if( dc > 25) i++;
if( dc > 50) i++;

act( msgs[i], ch, obj, NULL, TO_CHAR );
act( msgs[i], ch, NULL, NULL, TO_ROOM );
}
21 May, 2014, syn wrote in the 17th comment:
Votes: 0
Hi Quix,

Thanks for the input, the trailing false brace was a mistake in copying, as is indentation, it is indented well, to me, but it didnt appear to retain it quite right in the copy. I normally use notepad++ for editing, and upload via sftp to my nix vm.

The bit at the very top is the trail end of do_drop, continuing onto the new separate int function. The … portion was snipped but I missed tidying up the stray } it left.

The comment on int *dc, noted, thanks. I should probably get a class on C someday heh.

Good call on the case, I definitely missed that, and thanks for the different approach. I appreciate it.

Sorry about black with some red splashed in, that was kind of the point though, its obnoxious.. :P

-As an aside, minus the case of exactly 50, it seems to work perfectly at this point, but ill fix up that dc confusion I made for myself.
0.0/17