New Group System, Room Events, and Event System Efficiency Upgrade... and a couple bug fixes.

This commit is contained in:
Vatiken 2013-02-15 03:54:25 +00:00
parent 82da0e8063
commit a2aaab144f
32 changed files with 612 additions and 322 deletions

View file

@ -2,11 +2,13 @@ TbaMUD is currently being developed by The Builder Academy. If you need any
help, find any bugs, or have ideas for improvement please stop by TBA at
telnet://tbamud.com:9091 or email rumble@tbamud.com --Rumble
@
[Feb 12 2013] - Vatiken
feature: New group system.
feature: Room events.
bug: Many small bug fixes.
[Sep 08 2012] - Rumble
added another example to doc/syserr.txt
Added a !NPC check to can_take_object. It was spamming a "mob using player data SYSERR". This means mobs do not have a max weight carrying capacity anymore. I think this is a good thing because I've seen people stumped when mob triggers fail due to weight limitations. But it could be unbalancing on some MUDs since pets could then carry unlimited gear.
ht limitations. But it could be unbalancing on some MUDs since pets could then carry unlimited gear.
Uncommented code to prevent crashes when trying to save a deleted object.
[Aug 22 2012] - Rumble
bug: moved cedit load_config of no_mort_to_immort to its proper place. (thanks Liko)
[Aug 12 2012] - Vatiken

View file

@ -73,40 +73,25 @@ ACMD(do_say)
ACMD(do_gsay)
{
struct char_data *k;
struct follow_type *f;
skip_spaces(&argument);
if (!AFF_FLAGGED(ch, AFF_GROUP)) {
send_to_char(ch, "But you are not the member of a group!\r\n");
if (!GROUP(ch)) {
send_to_char(ch, "But you are not a member of a group!\r\n");
return;
}
if (!*argument)
send_to_char(ch, "Yes, but WHAT do you want to group-say?\r\n");
else {
char buf[MAX_STRING_LENGTH];
if (CONFIG_SPECIAL_IN_COMM && legal_communication(argument))
parse_at(argument);
if (ch->master)
k = ch->master;
else
k = ch;
snprintf(buf, sizeof(buf), "$n tells the group, '%s\tn'", argument);
if (AFF_FLAGGED(k, AFF_GROUP) && (k != ch))
act(buf, FALSE, ch, 0, k, TO_VICT | TO_SLEEP);
for (f = k->followers; f; f = f->next)
if (AFF_FLAGGED(f->follower, AFF_GROUP) && (f->follower != ch))
act(buf, FALSE, ch, 0, f->follower, TO_VICT | TO_SLEEP);
send_to_group(ch, ch->group, "%s%s%s says, '%s'%s\r\n", CCGRN(ch, C_NRM), CCGRN(ch, C_NRM), GET_NAME(ch), argument, CCNRM(ch, C_NRM));
if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
send_to_char(ch, "%s", CONFIG_OK);
else
send_to_char(ch, "You tell the group, '%s\tn'\r\n", argument);
send_to_char(ch, "%sYou group-say, '%s'%s\r\n", CCGRN(ch, C_NRM), argument, CCNRM(ch, C_NRM));
}
}

View file

@ -249,7 +249,6 @@ ACMD(do_sneak);
ACMD(do_split);
ACMD(do_steal);
ACMD(do_title);
ACMD(do_ungroup);
ACMD(do_visible);
@ -328,6 +327,7 @@ ACMD(do_plist);
ACMD(do_purge);
ACMD(do_recent);
ACMD(do_restore);
void return_to_char(struct char_data * ch);
ACMD(do_return);
ACMD(do_saveall);
ACMD(do_send);

View file

@ -309,6 +309,17 @@ static void list_one_char(struct char_data *i, struct char_data *ch)
}
}
if (GROUP(i)) {
if (GROUP(i) == GROUP(ch))
send_to_char(ch, "(%s%s%s) ", CBGRN(ch, C_NRM),
GROUP_LEADER(GROUP(i)) == i ? "leader" : "group",
CCNRM(ch, C_NRM));
else
send_to_char(ch, "(%s%s%s) ", CBRED(ch, C_NRM),
GROUP_LEADER(GROUP(i)) == i ? "leader" : "group",
CCNRM(ch, C_NRM));
}
if (IS_NPC(i) && i->player.long_descr && GET_POS(i) == GET_DEFAULT_POS(i)) {
if (AFF_FLAGGED(i, AFF_INVISIBLE))
send_to_char(ch, "*");
@ -1201,9 +1212,9 @@ ACMD(do_who)
continue;
if (showclass && !(showclass & (1 << GET_CLASS(tch))))
continue;
if (showgroup && (!tch->master || !AFF_FLAGGED(tch, AFF_GROUP)))
if (showgroup && !GROUP(tch))
continue;
if (showleader && (!tch->followers || !AFF_FLAGGED(tch, AFF_GROUP)))
if (showleader && (!GROUP(tch) || GROUP_LEADER(GROUP(tch)) != tch))
continue;
for (i = 0; *rank[i].disp != '\n'; i++)
if (GET_LEVEL(tch) >= rank[i].min_level && GET_LEVEL(tch) <= rank[i].max_level)
@ -1245,9 +1256,9 @@ ACMD(do_who)
continue;
if (showclass && !(showclass & (1 << GET_CLASS(tch))))
continue;
if (showgroup && (!tch->master || !AFF_FLAGGED(tch, AFF_GROUP)))
if (showgroup && !GROUP(tch))
continue;
if (showleader && (!tch->followers || !AFF_FLAGGED(tch, AFF_GROUP)))
if (showleader && (!GROUP(tch) || GROUP_LEADER(GROUP(tch)) != tch))
continue;
if (short_list) {

View file

@ -965,7 +965,7 @@ ACMD(do_follow)
}
if (ch->master)
stop_follower(ch);
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_GROUP);
add_follower(ch, leader);
}
}

View file

@ -35,9 +35,8 @@
/* Local defined utility functions */
/* do_group utility functions */
static int perform_group(struct char_data *ch, struct char_data *vict);
static void print_group(struct char_data *ch);
static void display_group_list(struct char_data * ch);
ACMD(do_quit)
{
@ -319,184 +318,171 @@ ACMD(do_title)
}
}
static int perform_group(struct char_data *ch, struct char_data *vict)
{
if (AFF_FLAGGED(vict, AFF_GROUP) || !CAN_SEE(ch, vict))
return (0);
SET_BIT_AR(AFF_FLAGS(vict), AFF_GROUP);
if (ch != vict)
act("$N is now a member of your group.", FALSE, ch, 0, vict, TO_CHAR);
act("You are now a member of $n's group.", FALSE, ch, 0, vict, TO_VICT);
act("$N is now a member of $n's group.", FALSE, ch, 0, vict, TO_NOTVICT);
return (1);
}
static void print_group(struct char_data *ch)
{
struct char_data * k;
struct follow_type *f;
if (!AFF_FLAGGED(ch, AFF_GROUP))
send_to_char(ch, "But you are not the member of a group!\r\n");
else {
char buf[MAX_STRING_LENGTH];
send_to_char(ch, "Your group consists of:\r\n");
k = (ch->master ? ch->master : ch);
if (AFF_FLAGGED(k, AFF_GROUP)) {
snprintf(buf, sizeof(buf), " [%3dH %3dM %3dV] [%2d %s] $N (Head of group)",
GET_HIT(k), GET_MANA(k), GET_MOVE(k), GET_LEVEL(k), CLASS_ABBR(k));
act(buf, FALSE, ch, 0, k, TO_CHAR);
while ((k = (struct char_data *) simple_list(ch->group->members)) != NULL)
send_to_char(ch, "%-*s: %s[%4d/%-4d]H [%4d/%-4d]M [%4d/%-4d]V%s\r\n",
count_color_chars(GET_NAME(k))+22, GET_NAME(k),
GROUP_LEADER(GROUP(ch)) == k ? CBGRN(ch, C_NRM) : CCGRN(ch, C_NRM),
GET_HIT(k), GET_MAX_HIT(k),
GET_MANA(k), GET_MAX_MANA(k),
GET_MOVE(k), GET_MAX_MOVE(k),
CCNRM(ch, C_NRM));
}
for (f = k->followers; f; f = f->next) {
if (!AFF_FLAGGED(f->follower, AFF_GROUP))
static void display_group_list(struct char_data * ch)
{
struct group_data * group;
int count = 0;
if (group_list->iSize) {
send_to_char(ch, "# Group Leader # of Members In Zone\r\n"
"---------------------------------------------------\r\n");
while ((group = (struct group_data *) simple_list(group_list)) != NULL) {
if (IS_SET(GROUP_FLAGS(group), GROUP_NPC))
continue;
if (GROUP_LEADER(group) && !IS_SET(GROUP_FLAGS(group), GROUP_ANON))
send_to_char(ch, "%-2d) %s%-12s %-2d %s%s\r\n",
++count,
IS_SET(GROUP_FLAGS(group), GROUP_OPEN) ? CCGRN(ch, C_NRM) : CCRED(ch, C_NRM),
GET_NAME(GROUP_LEADER(group)), group->members->iSize, zone_table[world[IN_ROOM(GROUP_LEADER(group))].zone].name,
CCNRM(ch, C_NRM));
else
send_to_char(ch, "%-2d) Hidden\r\n", ++count);
snprintf(buf, sizeof(buf), " [%3dH %3dM %3dV] [%2d %s] $N", GET_HIT(f->follower),
GET_MANA(f->follower), GET_MOVE(f->follower),
GET_LEVEL(f->follower), CLASS_ABBR(f->follower));
act(buf, FALSE, ch, 0, f->follower, TO_CHAR);
}
}
if (count)
send_to_char(ch, "\r\n"
"%sSeeking Members%s\r\n"
"%sClosed%s\r\n",
CCGRN(ch, C_NRM), CCNRM(ch, C_NRM),
CCRED(ch, C_NRM), CCNRM(ch, C_NRM));
else
send_to_char(ch, "\r\n"
"Currently no groups formed.\r\n");
}
/* Vatiken's Group System: Version 1.1 */
ACMD(do_group)
{
char buf[MAX_STRING_LENGTH];
struct char_data *vict;
struct follow_type *f;
int found;
one_argument(argument, buf);
argument = one_argument(argument, buf);
if (!*buf) {
if (GROUP(ch))
print_group(ch);
else
send_to_char(ch, "You must specify a group option, or type HELP GROUP for more info.\r\n");
return;
}
if (ch->master) {
act("You cannot enroll group members without being head of a group.",
FALSE, ch, 0, 0, TO_CHAR);
if (is_abbrev(buf, "new")) {
if (GROUP(ch))
send_to_char(ch, "You are already in a group.\r\n");
else
create_group(ch);
} else if (is_abbrev(buf, "list"))
display_group_list(ch);
else if (is_abbrev(buf, "join")) {
skip_spaces(&argument);
if (!(vict = get_char_vis(ch, argument, NULL, FIND_CHAR_ROOM))) {
send_to_char(ch, "Join who?\r\n");
return;
} else if (vict == ch) {
send_to_char(ch, "That would be one lonely grouping.\r\n");
return;
} else if (GROUP(ch)) {
send_to_char(ch, "But you are already part of a group.\r\n");
return;
} else if (!GROUP(vict)) {
send_to_char(ch, "They are not a part of a group!\r\n");
return;
} else if (!IS_SET(GROUP_FLAGS(GROUP(vict)), GROUP_OPEN)) {
send_to_char(ch, "That group isn't accepting members.\r\n");
return;
}
join_group(ch, GROUP(vict));
} else if (is_abbrev(buf, "kick")) {
skip_spaces(&argument);
if (!(vict = get_char_vis(ch, argument, NULL, FIND_CHAR_ROOM))) {
send_to_char(ch, "Kick out who?\r\n");
return;
} else if (vict == ch) {
send_to_char(ch, "There are easier ways to leave the group.\r\n");
return;
} else if (!GROUP(ch) ) {
send_to_char(ch, "But you are not part of a group.\r\n");
return;
} else if (GROUP_LEADER(GROUP(ch)) != ch ) {
send_to_char(ch, "Only the group's leader can kick members out.\r\n");
return;
} else if (GROUP(vict) != GROUP(ch)) {
send_to_char(ch, "They are not a member of your group!\r\n");
return;
}
send_to_char(ch, "You have kicked %s out of the group.\r\n", GET_NAME(vict));
send_to_char(vict, "You have been kicked out of the group.\r\n");
leave_group(vict);
} else if (is_abbrev(buf, "leave")) {
if (!GROUP(ch)) {
send_to_char(ch, "But you aren't apart of a group!\r\n");
return;
}
if (!str_cmp(buf, "all")) {
perform_group(ch, ch);
for (found = 0, f = ch->followers; f; f = f->next)
found += perform_group(ch, f->follower);
if (!found)
send_to_char(ch, "Everyone following you is already in your group.\r\n");
leave_group(ch);
} else if (is_abbrev(buf, "option")) {
skip_spaces(&argument);
if (!GROUP(ch)) {
send_to_char(ch, "But you aren't part of a group!\r\n");
return;
} else if (GROUP_LEADER(GROUP(ch)) != ch) {
send_to_char(ch, "Only the group leader can adjust the group flags.\r\n");
return;
}
if (!(vict = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM)))
send_to_char(ch, "%s", CONFIG_NOPERSON);
else if ((vict->master != ch) && (vict != ch))
act("$N must follow you to enter your group.", FALSE, ch, 0, vict, TO_CHAR);
else {
if (!AFF_FLAGGED(vict, AFF_GROUP))
perform_group(ch, vict);
else {
if (ch != vict)
act("$N is no longer a member of your group.", FALSE, ch, 0, vict, TO_CHAR);
act("You have been kicked out of $n's group!", FALSE, ch, 0, vict, TO_VICT);
act("$N has been kicked out of $n's group!", FALSE, ch, 0, vict, TO_NOTVICT);
REMOVE_BIT_AR(AFF_FLAGS(vict), AFF_GROUP);
}
}
if (is_abbrev(argument, "open")) {
TOGGLE_BIT(GROUP_FLAGS(GROUP(ch)), GROUP_OPEN);
send_to_char(ch, "The group is now %s to new members.\r\n", IS_SET(GROUP_FLAGS(GROUP(ch)), GROUP_OPEN) ? "open" : "closed");
} else if (is_abbrev(argument, "anonymous")) {
TOGGLE_BIT(GROUP_FLAGS(GROUP(ch)), GROUP_ANON);
send_to_char(ch, "The group location is now %s to other players.\r\n", IS_SET(GROUP_FLAGS(GROUP(ch)), GROUP_ANON) ? "invisible" : "visible");
} else
send_to_char(ch, "The flag options are: Open, Anonymous\r\n");
} else {
send_to_char(ch, "You must specify a group option, or type HELP GROUP for more info.\r\n");
}
ACMD(do_ungroup)
{
char buf[MAX_INPUT_LENGTH];
struct follow_type *f, *next_fol;
struct char_data *tch;
one_argument(argument, buf);
if (!*buf) {
if (ch->master || !(AFF_FLAGGED(ch, AFF_GROUP))) {
send_to_char(ch, "But you lead no group!\r\n");
return;
}
for (f = ch->followers; f; f = next_fol) {
next_fol = f->next;
if (AFF_FLAGGED(f->follower, AFF_GROUP)) {
REMOVE_BIT_AR(AFF_FLAGS(f->follower), AFF_GROUP);
act("$N has disbanded the group.", TRUE, f->follower, NULL, ch, TO_CHAR);
if (!AFF_FLAGGED(f->follower, AFF_CHARM))
stop_follower(f->follower);
}
}
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_GROUP);
send_to_char(ch, "You disband the group.\r\n");
return;
}
if (!(tch = get_char_vis(ch, buf, NULL, FIND_CHAR_ROOM))) {
send_to_char(ch, "There is no such person!\r\n");
return;
}
if (tch->master != ch) {
send_to_char(ch, "That person is not following you!\r\n");
return;
}
if (!AFF_FLAGGED(tch, AFF_GROUP)) {
send_to_char(ch, "That person isn't in your group.\r\n");
return;
}
REMOVE_BIT_AR(AFF_FLAGS(tch), AFF_GROUP);
act("$N is no longer a member of your group.", FALSE, ch, 0, tch, TO_CHAR);
act("You have been kicked out of $n's group!", FALSE, ch, 0, tch, TO_VICT);
act("$N has been kicked out of $n's group!", FALSE, ch, 0, tch, TO_NOTVICT);
if (!AFF_FLAGGED(tch, AFF_CHARM))
stop_follower(tch);
}
ACMD(do_report)
{
char buf[MAX_STRING_LENGTH];
struct char_data *k;
struct follow_type *f;
struct group_data *group;
if (!AFF_FLAGGED(ch, AFF_GROUP)) {
if ((group = GROUP(ch)) == NULL) {
send_to_char(ch, "But you are not a member of any group!\r\n");
return;
}
snprintf(buf, sizeof(buf), "$n reports: %d/%dH, %d/%dM, %d/%dV\r\n",
send_to_group(NULL, group, "%s reports: %d/%dH, %d/%dM, %d/%dV\r\n",
GET_NAME(ch),
GET_HIT(ch), GET_MAX_HIT(ch),
GET_MANA(ch), GET_MAX_MANA(ch),
GET_MOVE(ch), GET_MAX_MOVE(ch));
k = (ch->master ? ch->master : ch);
for (f = k->followers; f; f = f->next)
if (AFF_FLAGGED(f->follower, AFF_GROUP) && f->follower != ch)
act(buf, TRUE, ch, NULL, f->follower, TO_VICT);
if (k != ch)
act(buf, TRUE, ch, NULL, k, TO_VICT);
send_to_char(ch, "You report to the group.\r\n");
}
ACMD(do_split)
{
char buf[MAX_INPUT_LENGTH];
int amount, num, share, rest;
int amount, num = 0, share, rest;
size_t len;
struct char_data *k;
struct follow_type *f;
if (IS_NPC(ch))
return;
@ -513,20 +499,13 @@ ACMD(do_split)
send_to_char(ch, "You don't seem to have that much gold to split.\r\n");
return;
}
k = (ch->master ? ch->master : ch);
if (AFF_FLAGGED(k, AFF_GROUP) && (IN_ROOM(k) == IN_ROOM(ch)))
num = 1;
else
num = 0;
for (f = k->followers; f; f = f->next)
if (AFF_FLAGGED(f->follower, AFF_GROUP) &&
(!IS_NPC(f->follower)) &&
(IN_ROOM(f->follower) == IN_ROOM(ch)))
if (GROUP(ch))
while ((k = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL)
if (IN_ROOM(ch) == IN_ROOM(k) && !IS_NPC(k))
num++;
if (num && AFF_FLAGGED(ch, AFF_GROUP)) {
if (num && GROUP(ch)) {
share = amount / num;
rest = amount % num;
} else {
@ -544,22 +523,13 @@ ACMD(do_split)
"%d coin%s %s not splitable, so %s keeps the money.\r\n", rest,
(rest == 1) ? "" : "s", (rest == 1) ? "was" : "were", GET_NAME(ch));
}
if (AFF_FLAGGED(k, AFF_GROUP) && IN_ROOM(k) == IN_ROOM(ch) &&
!IS_NPC(k) && k != ch) {
while ((k = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL)
if (k != ch && IN_ROOM(ch) == IN_ROOM(k) && !IS_NPC(k)) {
increase_gold(k, share);
send_to_char(k, "%s", buf);
}
for (f = k->followers; f; f = f->next) {
if (AFF_FLAGGED(f->follower, AFF_GROUP) &&
(!IS_NPC(f->follower)) &&
(IN_ROOM(f->follower) == IN_ROOM(ch)) &&
f->follower != ch) {
increase_gold(f->follower, share);
send_to_char(f->follower, "%s", buf);
}
}
send_to_char(ch, "You split %d coins among %d members -- %d coins each.\r\n",
amount, num, share);

View file

@ -1245,20 +1245,8 @@ void do_cheat(struct char_data *ch)
save_char(ch);
}
ACMD(do_return)
void return_to_char(struct char_data * ch)
{
if (!IS_NPC(ch) && !ch->desc->original) {
int level, newlevel;
level = GET_LEVEL(ch);
do_cheat(ch);
newlevel = GET_LEVEL(ch);
if (!PLR_FLAGGED(ch, PLR_NOWIZLIST)&& level != newlevel)
run_autowiz();
}
if (ch->desc && ch->desc->original) {
send_to_char(ch, "You return to your original body.\r\n");
/* If someone switched into your original body, disconnect them. - JE
* Zmey: here we put someone switched in our body to disconnect state but
* we must also NULL his pointer to our character, otherwise close_socket()
@ -1277,6 +1265,22 @@ ACMD(do_return)
ch->desc->character->desc = ch->desc;
ch->desc = NULL;
}
ACMD(do_return)
{
if (!IS_NPC(ch) && !ch->desc->original) {
int level, newlevel;
level = GET_LEVEL(ch);
do_cheat(ch);
newlevel = GET_LEVEL(ch);
if (!PLR_FLAGGED(ch, PLR_NOWIZLIST)&& level != newlevel)
run_autowiz();
}
if (ch->desc && ch->desc->original) {
send_to_char(ch, "You return to your original body.\r\n");
return_to_char(ch);
}
}
ACMD(do_load)
@ -2169,7 +2173,6 @@ ACMD(do_wiznet)
int level = LVL_IMMORT;
skip_spaces(&argument);
delete_doubledollar(argument);
if (!*argument) {
send_to_char(ch, "Usage: wiznet [ #<level> ] [<text> | *<emotetext> | @ ]\r\n");
@ -3637,10 +3640,9 @@ ACMD (do_zcheck)
len += snprintf(buf + len, sizeof(buf) - len,
"- Has %d experience (limit: %d)\r\n",
GET_EXP(mob), MAX_EXP_ALLOWED);
if ((AFF_FLAGGED(mob, AFF_GROUP) || AFF_FLAGGED(mob, AFF_CHARM) || AFF_FLAGGED(mob, AFF_POISON)) && (found = 1))
if ((AFF_FLAGGED(mob, AFF_CHARM) || AFF_FLAGGED(mob, AFF_POISON)) && (found = 1))
len += snprintf(buf + len, sizeof(buf) - len,
"- Has illegal affection bits set (%s %s %s)\r\n",
AFF_FLAGGED(mob, AFF_GROUP) ? "GROUP" : "",
"- Has illegal affection bits set (%s %s)\r\n",
AFF_FLAGGED(mob, AFF_CHARM) ? "CHARM" : "",
AFF_FLAGGED(mob, AFF_POISON) ? "POISON" : "");
@ -4153,6 +4155,11 @@ ACMD(do_copyover)
/* For each playing descriptor, save its state */
for (d = descriptor_list; d ; d = d_next) {
struct char_data * och = d->character;
/* If d is currently in someone else's body, return them. */
if (och && d->original)
return_to_char(och);
/* We delete from the list , so need to save this */
d_next = d->next;

View file

@ -1609,6 +1609,7 @@ void init_spell_levels(void)
spell_level(SPELL_REMOVE_POISON, CLASS_CLERIC, 10);
spell_level(SPELL_IDENTIFY, CLASS_CLERIC, 11);
spell_level(SPELL_WORD_OF_RECALL, CLASS_CLERIC, 12);
spell_level(SPELL_DARKNESS, CLASS_CLERIC, 12);
spell_level(SPELL_EARTHQUAKE, CLASS_CLERIC, 12);
spell_level(SPELL_DISPEL_EVIL, CLASS_CLERIC, 14);
spell_level(SPELL_DISPEL_GOOD, CLASS_CLERIC, 14);

View file

@ -2418,6 +2418,29 @@ void send_to_room(room_rnum room, const char *messg, ...)
}
}
/* Sends a message to the entire group, except for ch.
* Send 'ch' as NULL, if you want to message to reach
* everyone. -Vatiken */
void send_to_group(struct char_data *ch, struct group_data *group, const char * msg, ...)
{
struct char_data *tch;
va_list args;
if (msg == NULL)
return;
while ((tch = simple_list(group->members)) != NULL) {
if (tch != ch && !IS_NPC(tch) && tch->desc && STATE(tch->desc) == CON_PLAYING) {
write_to_output(tch->desc, "%s[%sGroup%s]%s ",
CCGRN(tch, C_NRM), CBGRN(tch, C_NRM), CCGRN(tch, C_NRM), CCNRM(tch, C_NRM));
va_start(args, msg);
vwrite_to_output(tch->desc, msg, args);
va_end(args);
}
}
}
/* Thx to Jamie Nelson of 4D for this contribution */
void send_to_range(room_vnum start, room_vnum finish, const char *messg, ...)
{

View file

@ -27,6 +27,8 @@ void send_to_room(room_rnum room, const char *messg, ...) __attribute__ ((format
(printf, 2, 3)));
void send_to_outdoor(const char *messg, ...) __attribute__ ((format (printf, 1,
2)));
void send_to_group(struct char_data *ch, struct group_data *group, const char * msg, ...) __attribute__ ((format
(printf, 3, 4)));
void send_to_range(room_vnum start, room_vnum finish, const char *messg, ...)
__attribute__ ((format (printf, 3, 4)));

View file

@ -511,6 +511,16 @@ void destroy_db(void)
free(world[cnt].description);
free_extra_descriptions(world[cnt].ex_description);
if (world[cnt].events != NULL) {
if (world[cnt].events->iSize > 0) {
struct event * pEvent;
while ((pEvent = simple_list(world[cnt].events)) != NULL)
event_cancel(pEvent);
}
free_list(world[cnt].events);
}
/* free any assigned scripts */
if (SCRIPT(&world[cnt]))
extract_script(&world[cnt], WLD_TRIGGER);
@ -651,6 +661,7 @@ void boot_db(void)
log("Initialize Global Lists");
global_lists = create_list();
group_list = create_list();
log("Initializing Events");
init_events();
@ -1724,7 +1735,6 @@ void parse_mobile(FILE *mob_f, int nr)
/* Make some basic checks. */
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_CHARM);
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_POISON);
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_GROUP);
REMOVE_BIT_AR(AFF_FLAGS(mob_proto + i), AFF_SLEEP);
if (MOB_FLAGGED(mob_proto + i, MOB_AGGRESSIVE) && MOB_FLAGGED(mob_proto + i, MOB_AGGR_GOOD))
REMOVE_BIT_AR(MOB_FLAGS(mob_proto + i), MOB_AGGR_GOOD);
@ -2346,7 +2356,8 @@ struct char_data *create_char(void)
void new_mobile_data(struct char_data *ch)
{
ch->events = create_list();
ch->events = NULL;
ch->group = NULL;
}

View file

@ -935,11 +935,13 @@ ACMD(do_mtransform)
tmpmob.proto_script = ch->proto_script;
tmpmob.script = ch->script;
tmpmob.memory = ch->memory;
tmpmob.events = ch->events;
tmpmob.next_in_room = ch->next_in_room;
tmpmob.next = ch->next;
tmpmob.next_fighting = ch->next_fighting;
tmpmob.followers = ch->followers;
tmpmob.master = ch->master;
tmpmob.group = ch->group;
GET_WAS_IN(&tmpmob) = GET_WAS_IN(ch);
if (keep_hp) {

View file

@ -271,6 +271,10 @@ void raw_kill(struct char_data * ch, struct char_data * killer)
if (killer)
autoquest_trigger_check(killer, ch, NULL, AQ_MOB_KILL);
/* Alert Group if Applicable */
if (GROUP(ch))
send_to_group(ch, GROUP(ch), "%s has died.\r\n", GET_NAME(ch));
update_pos(ch);
make_corpse(ch);
@ -316,20 +320,11 @@ static void perform_group_gain(struct char_data *ch, int base,
static void group_gain(struct char_data *ch, struct char_data *victim)
{
int tot_members, base, tot_gain;
int tot_members = 0, base, tot_gain;
struct char_data *k;
struct follow_type *f;
if (!(k = ch->master))
k = ch;
if (AFF_FLAGGED(k, AFF_GROUP) && (IN_ROOM(k) == IN_ROOM(ch)))
tot_members = 1;
else
tot_members = 0;
for (f = k->followers; f; f = f->next)
if (AFF_FLAGGED(f->follower, AFF_GROUP) && IN_ROOM(f->follower) == IN_ROOM(ch))
while ((k = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL)
if (IN_ROOM(ch) == IN_ROOM(k))
tot_members++;
/* round up to the nearest tot_members */
@ -344,12 +339,9 @@ static void group_gain(struct char_data *ch, struct char_data *victim)
else
base = 0;
if (AFF_FLAGGED(k, AFF_GROUP) && IN_ROOM(k) == IN_ROOM(ch))
while ((k = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL)
if (IN_ROOM(k) == IN_ROOM(ch))
perform_group_gain(k, base, victim);
for (f = k->followers; f; f = f->next)
if (AFF_FLAGGED(f->follower, AFF_GROUP) && IN_ROOM(f->follower) == IN_ROOM(ch))
perform_group_gain(f->follower, base, victim);
}
static void solo_gain(struct char_data *ch, struct char_data *victim)
@ -738,7 +730,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
/* Uh oh. Victim died. */
if (GET_POS(victim) == POS_DEAD) {
if (ch != victim && (IS_NPC(victim) || victim->desc)) {
if (AFF_FLAGGED(ch, AFF_GROUP))
if (GROUP(ch))
group_gain(ch, victim);
else
solo_gain(ch, victim);
@ -762,7 +754,7 @@ int damage(struct char_data *ch, struct char_data *victim, int dam, int attackty
}
die(victim, ch);
if (IS_AFFECTED(ch, AFF_GROUP) && (local_gold > 0) && PRF_FLAGGED(ch, PRF_AUTOSPLIT) ) {
if (GROUP(ch) && (local_gold > 0) && PRF_FLAGGED(ch, PRF_AUTOSPLIT) ) {
generic_find("corpse", FIND_OBJ_ROOM, ch, &tmp_char, &corpse_obj);
if (corpse_obj) {
do_get(ch, "all.coin corpse", 0, 0);
@ -905,8 +897,7 @@ void hit(struct char_data *ch, struct char_data *victim, int type)
/* control the fights going on. Called every 2 seconds from comm.c. */
void perform_violence(void)
{
struct char_data *ch;
struct follow_type *k;
struct char_data *ch, *tch;
for (ch = combat_list; ch; ch = next_combat_list) {
next_combat_list = ch->next_fighting;
@ -933,18 +924,24 @@ void perform_violence(void)
continue;
}
for (k = ch->followers; k; k=k->next) {
/* should followers auto-assist master? */
if (!IS_NPC(k->follower) && !FIGHTING(k->follower) && PRF_FLAGGED(k->follower,
PRF_AUTOASSIST) && (IN_ROOM(k->follower) == IN_ROOM(ch)))
do_assist(k->follower, GET_NAME(ch), 0, 0);
}
if (GROUP(ch)) {
while ((tch = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL) {
if (tch == ch)
continue;
if (!IS_NPC(tch) && !PRF_FLAGGED(tch, PRF_AUTOASSIST))
continue;
if (IN_ROOM(ch) != IN_ROOM(tch))
continue;
if (FIGHTING(tch))
continue;
if (GET_POS(tch) != POS_STANDING)
continue;
if (!CAN_SEE(tch, ch))
continue;
/* should master auto-assist followers? */
if (ch->master && PRF_FLAGGED(ch->master, PRF_AUTOASSIST) &&
FIGHTING(ch) && !FIGHTING(ch->master) && !IS_NPC(ch) &&
(IN_ROOM(ch->master) == IN_ROOM(ch)) && !IS_NPC(ch->master))
do_assist(ch->master, GET_NAME(ch), 0, 0);
do_assist(tch, GET_NAME(ch), 0, 0);
}
}
hit(ch, FIGHTING(ch), TYPE_UNDEFINED);
if (MOB_FLAGGED(ch, MOB_SPEC) && GET_MOB_SPEC(ch) && !MOB_FLAGGED(ch, MOB_NOTDEADYET)) {

View file

@ -17,6 +17,7 @@
#include "genzon.h"
#include "shop.h"
#include "dg_olc.h"
#include "mud_event.h"
/* This function will copy the strings so be sure you free your own copies of
@ -167,6 +168,16 @@ int delete_room(room_rnum rnum)
extract_script(room, WLD_TRIGGER);
free_proto_script(room, WLD_TRIGGER);
if (room->events != NULL) {
if (room->events->iSize > 0) {
struct event * pEvent;
while ((pEvent = simple_list(room->events)) != NULL)
event_cancel(pEvent);
}
free_list(room->events);
}
/* Change any exit going to this room to go the void. Also fix all the exits
* pointing to rooms above this. */
i = top_of_world + 1;
@ -378,10 +389,12 @@ int copy_room(struct room_data *to, struct room_data *from)
free_room_strings(to);
*to = *from;
copy_room_strings(to, from);
to->events = from->events;
/* Don't put people and objects in two locations. Should this be done here? */
from->people = NULL;
from->contents = NULL;
from->events = NULL;
return TRUE;
}

View file

@ -74,6 +74,12 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
} else if (bottom > top) {
*error = "Bottom room cannot be greater than top room.\r\n";
return NOWHERE;
} else if (bottom < 0) {
*error = "Bottom room cannot be less then 0.\r\n";
return NOWHERE;
} else if (top >= IDXTYPE_MAX) {
*error = "Top greater than IDXTYPE_MAX. (Commonly 65535)\r\n";
return NOWHERE;
}
for (i = 0; i < top_of_zone_table; i++)

View file

@ -15,6 +15,7 @@
#include "comm.h"
#include "db.h"
#include "handler.h"
#include "screen.h"
#include "interpreter.h"
#include "spells.h"
#include "dg_scripts.h"
@ -22,6 +23,7 @@
#include "class.h"
#include "fight.h"
#include "quest.h"
#include "mud_event.h"
/* local file scope variables */
static int extractions_pending = 0;
@ -910,6 +912,10 @@ void extract_char_final(struct char_data *ch)
if (ch->followers || ch->master)
die_follower(ch);
/* Check to see if we are grouped! */
if (GROUP(ch))
leave_group(ch);
/* transfer objects to room, if any */
while (ch->carrying) {
obj = ch->carrying;
@ -1386,3 +1392,100 @@ int find_all_dots(char *arg)
} else
return (FIND_INDIV);
}
/* Group Handlers */
struct group_data * create_group(struct char_data * leader)
{
struct group_data * new_group;
/* Allocate Group Memory & Attach to Group List*/
CREATE(new_group, struct group_data, 1);
add_to_list(new_group, group_list);
/* Allocate Members List */
new_group->members = create_list();
/* Clear Data */
new_group->group_flags = 0;
/* Assign Data */
SET_BIT(GROUP_FLAGS(new_group), GROUP_OPEN);
if (IS_NPC(leader))
SET_BIT(GROUP_FLAGS(new_group), GROUP_NPC);
join_group(leader, new_group);
return (new_group);
}
void free_group(struct group_data * group)
{
struct char_data *tch;
struct iterator_data Iterator;
if (group->members->iSize) {
for (tch = (struct char_data *) merge_iterator(&Iterator, group->members);
tch;
tch = next_in_list(&Iterator))
leave_group(tch);
remove_iterator(&Iterator);
}
free_list(group->members);
remove_from_list(group, group_list);
free(group);
}
void leave_group(struct char_data *ch)
{
struct group_data *group;
struct char_data *tch;
struct iterator_data Iterator;
bool found_pc = FALSE;
if ((group = ch->group) == NULL)
return;
send_to_group(NULL, group, "%s has left the group.\r\n", GET_NAME(ch));
remove_from_list(ch, group->members);
ch->group = NULL;
if (group->members->iSize) {
for (tch = (struct char_data *) merge_iterator(&Iterator, group->members);
tch; tch = next_in_list(&Iterator))
if (!IS_NPC(tch))
found_pc = TRUE;
remove_iterator(&Iterator);
}
if (!found_pc)
SET_BIT(GROUP_FLAGS(group), GROUP_NPC);
if (GROUP_LEADER(group) == ch && group->members->iSize) {
group->leader = (struct char_data *) random_from_list(group->members);
send_to_group(NULL, group, "%s has assumed leadership of the group.\r\n", GET_NAME(GROUP_LEADER(group)));
} else if (group->members->iSize == 0)
free_group(group);
}
void join_group(struct char_data *ch, struct group_data *group)
{
add_to_list(ch, group->members);
if (group->leader == NULL)
group->leader = ch;
ch->group = group;
if (IS_SET(group->group_flags, GROUP_NPC) && !IS_NPC(ch))
REMOVE_BIT(GROUP_FLAGS(group), GROUP_NPC);
if (group->leader == ch)
send_to_group(NULL, group, "%s becomes leader of the group.\r\n", GET_NAME(ch));
else
send_to_group(NULL, group, "%s joins the group.\r\n", GET_NAME(ch));
}

View file

@ -77,6 +77,11 @@ int find_all_dots(char *arg);
#define FIND_ALL 1
#define FIND_ALLDOT 2
/* group */
struct group_data * create_group(struct char_data * leader);
void free_group(struct group_data * group);
void leave_group(struct char_data *ch);
void join_group(struct char_data *ch, struct group_data *group);
/* Generic Find */
int generic_find(char *arg, bitvector_t bitvector, struct char_data *ch,

View file

@ -323,7 +323,6 @@ cpp_extern const struct command_info cmd_info[] = {
{ "tstat" , "tstat" , POS_DEAD , do_tstat , LVL_BUILDER, 0 },
{ "unlock" , "unlock" , POS_SITTING , do_gen_door , 0, SCMD_UNLOCK },
{ "ungroup" , "ungroup" , POS_DEAD , do_ungroup , 0, 0 },
{ "unban" , "unban" , POS_DEAD , do_unban , LVL_GRGOD, 0 },
{ "unaffect" , "unaffect", POS_DEAD , do_wizutil , LVL_GOD, SCMD_UNAFFECT },
{ "uptime" , "uptime" , POS_DEAD , do_date , LVL_GOD, SCMD_UPTIME },
@ -1140,7 +1139,6 @@ static int perform_dupe_check(struct descriptor_data *d)
d->character->char_specials.timer = 0;
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_MAILING);
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_WRITING);
REMOVE_BIT_AR(AFF_FLAGS(d->character), AFF_GROUP);
STATE(d) = CON_PLAYING;
MXPSendTag( d, "<VERSION>" );
@ -1416,7 +1414,6 @@ void nanny(struct descriptor_data *d, char *arg)
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_WRITING);
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_MAILING);
REMOVE_BIT_AR(PLR_FLAGS(d->character), PLR_CRYO);
REMOVE_BIT_AR(AFF_FLAGS(d->character), AFF_GROUP);
d->character->player.time.logon = time(0);
write_to_output(d, "Password: ");
echo_off(d);

View file

@ -12,8 +12,13 @@
#include "db.h"
#include "dg_event.h"
static struct iterator_data Iterator;
static bool loop = FALSE;
static struct list_data *pLastList = NULL;
/* Global lists */
struct list_data * global_lists = NULL;
struct list_data * group_list = NULL;
struct list_data * create_list(void)
{
@ -53,7 +58,7 @@ void free_list(struct list_data * pList)
{
void * pContent;
simple_list(NULL);
clear_simple_list();
if (pList->iSize)
while ((pContent = simple_list(pList)))
@ -225,6 +230,12 @@ struct item_data * find_in_list(void * pContent, struct list_data * pList)
return NULL;
}
void clear_simple_list(void)
{
loop = FALSE;
pLastList = NULL;
}
/** This is the "For Dummies" function, as although it's not as flexible,
* it is even easier applied for list searches then using your own iterators
* and next_in_list()
@ -239,15 +250,11 @@ struct item_data * find_in_list(void * pContent, struct list_data * pList)
void * simple_list(struct list_data * pList)
{
static struct iterator_data Iterator;
static bool loop = FALSE;
static struct list_data *pLastList = NULL;
void * pContent;
/* Reset List */
if (pList == NULL) {
loop = FALSE;
pLastList = NULL;
clear_simple_list();
return NULL;
}

View file

@ -33,6 +33,7 @@ struct iterator_data {
/* Externals */
extern struct list_data * global_lists;
extern struct list_data * group_list;
/* Locals */
void add_to_list(void * pContent, struct list_data * pList);
@ -46,4 +47,5 @@ void remove_from_list(void * pContent, struct list_data * pList);
struct item_data * find_in_list(void * pContent, struct list_data * pList);
void * simple_list(struct list_data * pList);
void free_list(struct list_data * pList);
void clear_simple_list(void);
#endif

View file

@ -21,6 +21,7 @@
#include "dg_scripts.h"
#include "class.h"
#include "fight.h"
#include "mud_event.h"
/* local file scope function prototypes */
@ -574,35 +575,22 @@ static void perform_mag_groups(int level, struct char_data *ch,
* Just add a new case to perform_mag_groups. */
void mag_groups(int level, struct char_data *ch, int spellnum, int savetype)
{
struct char_data *tch, *k;
struct follow_type *f, *f_next;
struct char_data *tch;
if (ch == NULL)
return;
if (!AFF_FLAGGED(ch, AFF_GROUP))
if (!GROUP(ch))
return;
if (ch->master != NULL)
k = ch->master;
else
k = ch;
for (f = k->followers; f; f = f_next) {
f_next = f->next;
tch = f->follower;
while ((tch = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL) {
if (IN_ROOM(tch) != IN_ROOM(ch))
continue;
if (!AFF_FLAGGED(tch, AFF_GROUP))
continue;
if (ch == tch)
continue;
perform_mag_groups(level, ch, tch, spellnum, savetype);
}
if ((k != ch) && AFF_FLAGGED(k, AFF_GROUP))
perform_mag_groups(level, ch, k, spellnum, savetype);
perform_mag_groups(level, ch, ch, spellnum, savetype);
}
/* Mass spells affect every creature in the room except the caster. No spells
* of this class currently implemented. */
void mag_masses(int level, struct char_data *ch, int spellnum, int savetype)
@ -663,8 +651,7 @@ void mag_areas(int level, struct char_data *ch, int spellnum, int savetype)
continue;
if (!IS_NPC(ch) && IS_NPC(tch) && AFF_FLAGGED(tch, AFF_CHARM))
continue;
if (!IS_NPC(tch) && spell_info[spellnum].violent && AFF_FLAGGED(tch, AFF_GROUP) && AFF_FLAGGED(ch, AFF_GROUP) &&
( ((ch->master == NULL) ? ch : ch->master) == ((tch->master == NULL) ? tch : tch->master) ) )
if (!IS_NPC(tch) && spell_info[spellnum].violent && GROUP(tch) && GROUP(ch) && GROUP(ch) == GROUP(tch))
continue;
if ((spellnum == SPELL_EARTHQUAKE) && AFF_FLAGGED(tch, AFF_FLYING))
continue;
@ -784,6 +771,9 @@ void mag_summons(int level, struct char_data *ch, struct obj_data *obj,
act(mag_summon_msgs[msg], FALSE, ch, 0, mob, TO_ROOM);
load_mtrigger(mob);
add_follower(mob, ch);
if (GROUP(ch) && GROUP_LEADER(GROUP(ch)) == ch)
join_group(mob, GROUP(ch));
}
if (handle_corpse) {
for (tobj = obj->contains; tobj; tobj = next_obj) {
@ -976,3 +966,42 @@ void mag_creations(int level, struct char_data *ch, int spellnum)
load_otrigger(tobj);
}
void mag_rooms(int level, struct char_data *ch, int spellnum)
{
room_rnum rnum;
int duration;
bool failure = FALSE;
event_id IdNum = -1;
const char *msg = NULL;
const char *room = NULL;
rnum = IN_ROOM(ch);
if (ROOM_FLAGGED(rnum, ROOM_NOMAGIC))
failure = TRUE;
switch (spellnum) {
case SPELL_DARKNESS:
IdNum = eSPL_DARKNESS;
if (ROOM_FLAGGED(rnum, ROOM_DARK))
failure = TRUE;
duration = 5;
SET_BIT_AR(ROOM_FLAGS(rnum), ROOM_DARK);
msg = "You cast a shroud of darkness upon the area.";
room = "$n casts a shroud of darkness upon this area.";
break;
}
if (failure || IdNum == -1) {
send_to_char(ch, "You failed!\r\n");
return;
}
send_to_char(ch, "%s\r\n", msg);
act(room, FALSE, ch, 0, 0, TO_ROOM);
NEW_EVENT(eSPL_DARKNESS, &world[rnum], NULL, duration * PASSES_PER_SEC);
}

View file

@ -901,7 +901,6 @@ void medit_parse(struct descriptor_data *d, char *arg)
/* Remove unwanted bits right away. */
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_CHARM);
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_POISON);
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_GROUP);
REMOVE_BIT_AR(AFF_FLAGS(OLC_MOB(d)), AFF_SLEEP);
medit_disp_aff_flags(d);
return;

View file

@ -155,6 +155,8 @@ void mobile_activity(void)
for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room)
{
if (ch == vict || !IS_NPC(vict) || !FIGHTING(vict))
continue;
if (GROUP(vict) && GROUP(vict) == GROUP(ch))
continue;
if (IS_NPC(FIGHTING(vict)) || ch == FIGHTING(vict))
continue;

View file

@ -23,7 +23,8 @@ struct list_data * world_events = NULL;
struct mud_event_list mud_event_index[] = {
{ "Null" , NULL , -1 }, /* eNULL */
{ "Protocol" , get_protocols , EVENT_DESC }, /* ePROTOCOLS */
{ "Whirlwind" , event_whirlwind, EVENT_CHAR } /* eWHIRLWIND */
{ "Whirlwind" , event_whirlwind, EVENT_CHAR }, /* eWHIRLWIND */
{ "Spell:Darkness",event_countdown, EVENT_ROOM } /* eSPL_DARKNESS */
};
/* init_events() is the ideal function for starting global events. This
@ -54,6 +55,8 @@ EVENTFUNC(event_countdown)
{
struct mud_event_data * pMudEvent;
struct char_data * ch = NULL;
struct room_data * room = NULL;
room_rnum rnum = NOWHERE;
pMudEvent = (struct mud_event_data * ) event_obj;
@ -61,11 +64,19 @@ EVENTFUNC(event_countdown)
case EVENT_CHAR:
ch = (struct char_data * ) pMudEvent->pStruct;
break;
case EVENT_ROOM:
room = (struct room_data * ) pMudEvent->pStruct;
rnum = real_room(room->number);
break;
default:
break;
}
switch (pMudEvent->iId) {
case eSPL_DARKNESS:
REMOVE_BIT_AR(ROOM_FLAGS(rnum), ROOM_DARK);
send_to_room(rnum, "The dark shroud disappates.\r\n");
break;
default:
break;
}
@ -82,6 +93,7 @@ void attach_mud_event(struct mud_event_data *pMudEvent, long time)
struct event * pEvent;
struct descriptor_data * d;
struct char_data * ch;
struct room_data * room;
pEvent = event_create(mud_event_index[pMudEvent->iId].func, pMudEvent, time);
pEvent->isMudEvent = TRUE;
@ -97,8 +109,20 @@ void attach_mud_event(struct mud_event_data *pMudEvent, long time)
break;
case EVENT_CHAR:
ch = (struct char_data *) pMudEvent->pStruct;
if (ch->events == NULL)
ch->events = create_list();
add_to_list(pEvent, ch->events);
break;
case EVENT_ROOM:
room = (struct room_data *) pMudEvent->pStruct;
if (room->events == NULL)
room->events = create_list();
add_to_list(pEvent, room->events);
break;
}
}
@ -122,6 +146,7 @@ void free_mud_event(struct mud_event_data *pMudEvent)
{
struct descriptor_data * d;
struct char_data * ch;
struct room_data * room;
switch (mud_event_index[pMudEvent->iId].iEvent_Type) {
case EVENT_WORLD:
@ -134,6 +159,20 @@ void free_mud_event(struct mud_event_data *pMudEvent)
case EVENT_CHAR:
ch = (struct char_data *) pMudEvent->pStruct;
remove_from_list(pMudEvent->pEvent, ch->events);
if (ch->events->iSize == 0) {
free_list(ch->events);
ch->events = NULL;
}
break;
case EVENT_ROOM:
room = (struct room_data *) pMudEvent->pStruct;
remove_from_list(pMudEvent->pEvent, room->events);
if (room->events->iSize == 0) {
free_list(room->events);
room->events = NULL;
}
break;
}
@ -150,10 +189,13 @@ struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId)
struct mud_event_data * pMudEvent;
bool found = FALSE;
if (ch->events == NULL)
return NULL;
if (ch->events->iSize == 0)
return NULL;
simple_list(NULL);
clear_simple_list();
while ((pEvent = (struct event *) simple_list(ch->events)) != NULL) {
if (!pEvent->isMudEvent)
@ -165,8 +207,6 @@ struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId)
}
}
simple_list(NULL);
if (found)
return (pMudEvent);
@ -183,11 +223,46 @@ void clear_char_event_list(struct char_data * ch)
if (ch->events->iSize == 0)
return;
simple_list(NULL);
clear_simple_list();
while ((pEvent = (struct event *) simple_list(ch->events)) != NULL) {
event_cancel(pEvent);
}
simple_list(NULL);
}
/* change_event_duration contributed by Ripley */
void change_event_duration(struct char_data * ch, event_id iId, long time) {
struct event * pEvent;
struct mud_event_data * pMudEvent;
bool found = FALSE;
if (ch->events == NULL);
return;
if (ch->events->iSize == 0)
return;
clear_simple_list();
while ((pEvent = (struct event *) simple_list(ch->events)) != NULL) {
if (!pEvent->isMudEvent)
continue;
pMudEvent = (struct mud_event_data * ) pEvent->event_obj;
if (pMudEvent->iId == iId) {
found = TRUE;
break;
}
}
if (found) {
/* So we found the offending event, now build a new one, with the new time */
attach_mud_event(new_mud_event(iId, pMudEvent->pStruct, pMudEvent->sVariables), time);
event_cancel(pEvent);
}
}

View file

@ -18,6 +18,7 @@
#define EVENT_WORLD 0
#define EVENT_DESC 1
#define EVENT_CHAR 2
#define EVENT_ROOM 3
#define NEW_EVENT(event_id, struct, var, time) (attach_mud_event(new_mud_event(event_id, struct, var), time))
@ -25,6 +26,7 @@ typedef enum {
eNULL,
ePROTOCOLS, /* The Protocol Detection Event */
eWHIRLWIND, /* The Whirlwind Attack */
eSPL_DARKNESS, /* Darkness Spell */
} event_id;
struct mud_event_list {

View file

@ -1026,11 +1026,15 @@ obj_save_data *objsave_parse_objects(FILE *fl)
if (*line == '#') {
/* check for false alarm. */
if (sscanf(line, "#%d", &nr) == 1) {
/* Do not save an object if it has been deleted */
if (real_object(nr) == NOTHING) {
log("SYSERR: Protection: deleting object %d.", nr);
/* If we attempt to load an object with a legal VNUM 0-65534, that
* does not exist, skip it. If the object has a VNUM of NOTHING or
* 65535, then we assume it doesn't exist on purpose. (Custom Item,
* Coins, Corpse, etc...) */
if (real_object(nr) == NOTHING && nr != NOTHING) {
log("SYSERR: Prevented loading of non-existant item #%d.", nr);
continue;
}
if (temp) {
current->obj = temp;
CREATE(current->next, obj_save_data, 1);
@ -1060,12 +1064,11 @@ obj_save_data *objsave_parse_objects(FILE *fl)
continue;
}
/* Should never get here, but since we did in the past, I'll put
* a safety check in. */
if (temp == NULL) {
log("SYSERR: Attempting to parse obj_save_data on NULL object.");
abort();
}
/* If "temp" is NULL, we are most likely progressing through
* a non-existant object, so just keep continuing till we find
* the next object */
if (temp == NULL)
continue;
tag_argument(line, tag);
num = atoi(line);

View file

@ -177,6 +177,9 @@ void redit_setup_existing(struct descriptor_data *d, int real_num)
/* and you are your next_in_room -- anderyu (10-05-22) */
room->people = NULL;
/* Nullify the events structure. */
room->events = NULL;
/* Allocate space for all strings. */
room->name = str_udup(world[real_num].name);
room->description = str_udup(world[real_num].description);

View file

@ -263,6 +263,9 @@ int call_magic(struct char_data *caster, struct char_data *cvict,
if (IS_SET(SINFO.routines, MAG_CREATIONS))
mag_creations(level, caster, spellnum);
if (IS_SET(SINFO.routines, MAG_ROOMS))
mag_rooms(level, caster, spellnum);
if (IS_SET(SINFO.routines, MAG_MANUAL))
switch (spellnum) {
case SPELL_CHARM: MANUAL_SPELL(spell_charm); break;
@ -473,7 +476,7 @@ int cast_spell(struct char_data *ch, struct char_data *tch,
send_to_char(ch, "You cannot cast this spell upon yourself!\r\n");
return (0);
}
if (IS_SET(SINFO.routines, MAG_GROUPS) && !AFF_FLAGGED(ch, AFF_GROUP)) {
if (IS_SET(SINFO.routines, MAG_GROUPS) && !GROUP(ch)) {
send_to_char(ch, "You can't cast this spell if you're not in a group!\r\n");
return (0);
}
@ -789,6 +792,10 @@ void mag_assign_spells(void)
TAR_CHAR_ROOM | TAR_OBJ_INV, TRUE, MAG_AFFECTS | MAG_ALTER_OBJS,
"You feel more optimistic.");
spello(SPELL_DARKNESS, "darkness", 30, 5, 4, POS_STANDING,
TAR_IGNORE, FALSE, MAG_ROOMS,
NULL);
spello(SPELL_DETECT_ALIGN, "detect alignment", 20, 10, 2, POS_STANDING,
TAR_CHAR_ROOM | TAR_SELF_ONLY, FALSE, MAG_AFFECTS,
"You feel less aware.");

View file

@ -33,6 +33,7 @@
#define MAG_SUMMONS (1 << 8)
#define MAG_CREATIONS (1 << 9)
#define MAG_MANUAL (1 << 10)
#define MAG_ROOMS (1 << 11)
#define TYPE_UNDEFINED (-1)
#define SPELL_RESERVED_DBC 0 /* SKILL NUMBER ZERO -- RESERVED */
@ -91,8 +92,9 @@
#define SPELL_WATERWALK 51 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_IDENTIFY 52 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_FLY 53 /* Reserved Skill[] DO NOT CHANGE */
#define SPELL_DARKNESS 54
/** Total Number of defined spells */
#define NUM_SPELLS 53
#define NUM_SPELLS 54
/* Insert new spells here, up to MAX_SPELLS */
#define MAX_SPELLS 130
@ -241,6 +243,8 @@ void mag_masses(int level, struct char_data *ch, int spellnum, int savetype);
void mag_areas(int level, struct char_data *ch, int spellnum, int savetype);
void mag_rooms(int level, struct char_data *ch, int spellnum);
void mag_summons(int level, struct char_data *ch, struct obj_data *obj,
int spellnum, int savetype);

View file

@ -148,6 +148,11 @@
#define HISTORY_SIZE 5 /**< Number of last commands kept in each history */
/* Group Defines */
#define GROUP_OPEN (1 << 0) /**< Group is open for members */
#define GROUP_ANON (1 << 1) /**< Group is Anonymous */
#define GROUP_NPC (1 << 2) /**< Group created by NPC and thus not listed */
/* PC classes */
#define CLASS_UNDEFINED (-1) /**< PC Class undefined */
#define CLASS_MAGIC_USER 0 /**< PC Class Magic User */
@ -280,7 +285,7 @@
#define AFF_SENSE_LIFE 6 /**< Char can sense hidden life */
#define AFF_WATERWALK 7 /**< Char can walk on water */
#define AFF_SANCTUARY 8 /**< Char protected by sanct */
#define AFF_GROUP 9 /**< (R) Char is grouped */
#define AFF_UNUSED 9 /**< (R) Char is grouped */
#define AFF_CURSE 10 /**< Char is cursed */
#define AFF_INFRAVISION 11 /**< Char can see in dark */
#define AFF_POISON 12 /**< (R) Char is poisoned */
@ -804,6 +809,8 @@ struct room_data
struct script_data *script; /**< script info for the room */
struct obj_data *contents; /**< List of items in room */
struct char_data *people; /**< List of NPCs / PCs in room */
struct list_data * events;
};
/* char-related structures */
@ -835,6 +842,15 @@ struct time_data
int played; /**< This is the total accumulated time played in secs */
};
/* Group Data Struct */
struct group_data
{
struct char_data * leader;
struct list_data * members;
int group_flags;
};
/** The pclean_criteria_data is set up in config.c and used in db.c to determine
* the conditions which will cause a player character to be deleted from disk
* if the automagic pwipe system is enabled (see config.c). */
@ -1035,6 +1051,8 @@ struct char_data
struct follow_type *followers; /**< List of characters following */
struct char_data *master; /**< List of character being followed */
struct group_data *group; /**< Character's Group */
long pref; /**< unique session id */
struct list_data * events;

View file

@ -573,7 +573,6 @@ void stop_follower(struct char_data *ch)
ch->master = NULL;
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_CHARM);
REMOVE_BIT_AR(AFF_FLAGS(ch), AFF_GROUP);
}
/** Finds the number of follows that are following, and charmed by, the

View file

@ -867,6 +867,11 @@ do \
/** Defines if ch is outdoors or not. */
#define OUTSIDE(ch) (!ROOM_FLAGGED(IN_ROOM(ch), ROOM_INDOORS))
/* Group related defines */
#define GROUP(ch) (ch->group)
#define GROUP_LEADER(group) (group->leader)
#define GROUP_FLAGS(group) (group->group_flags)
/* Happy-hour defines */
#define IS_HAPPYQP (happy_data.qp_rate > 0)
#define IS_HAPPYEXP (happy_data.exp_rate > 0)