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

@ -73,41 +73,26 @@ 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);
parse_at(argument);
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));
}
}
static void perform_tell(struct char_data *ch, struct char_data *vict, char *arg)

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,185 +318,172 @@ 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;
struct char_data * k;
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");
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);
}
for (f = k->followers; f; f = f->next) {
if (!AFF_FLAGGED(f->follower, AFF_GROUP))
continue;
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);
}
}
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));
}
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);
}
}
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) {
print_group(ch);
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);
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");
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);
}
}
}
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");
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;
}
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);
}
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;
}
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 (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");
}
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 (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 (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)))
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) {
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) {
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);
}
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,6 +1245,27 @@ void do_cheat(struct char_data *ch)
save_char(ch);
}
void return_to_char(struct char_data * ch)
{
/* 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()
* will damage our character's pointer to our descriptor (which is assigned
* below in this function). */
if (ch->desc->original->desc) {
ch->desc->original->desc->character = NULL;
STATE(ch->desc->original->desc) = CON_DISCONNECT;
}
/* Now our descriptor points to our original body. */
ch->desc->character = ch->desc->original;
ch->desc->original = NULL;
/* And our body's pointer to descriptor now points to our descriptor. */
ch->desc->character->desc = ch->desc;
ch->desc = NULL;
}
ACMD(do_return)
{
if (!IS_NPC(ch) && !ch->desc->original) {
@ -1258,24 +1279,7 @@ ACMD(do_return)
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()
* will damage our character's pointer to our descriptor (which is assigned
* below in this function). */
if (ch->desc->original->desc) {
ch->desc->original->desc->character = NULL;
STATE(ch->desc->original->desc) = CON_DISCONNECT;
}
/* Now our descriptor points to our original body. */
ch->desc->character = ch->desc->original;
ch->desc->original = NULL;
/* And our body's pointer to descriptor now points to our descriptor. */
ch->desc->character->desc = ch->desc;
ch->desc = NULL;
return_to_char(ch);
}
}
@ -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

@ -872,18 +872,18 @@ ACMD(do_mtransform)
int keep_hp = 1; /* new mob keeps the old mob's hp/max hp/exp */
int pos;
if (!MOB_OR_IMPL(ch)) {
send_to_char(ch, "Huh?!?\r\n");
return;
}
if (!MOB_OR_IMPL(ch)) {
send_to_char(ch, "Huh?!?\r\n");
return;
}
if (AFF_FLAGGED(ch, AFF_CHARM))
return;
if (AFF_FLAGGED(ch, AFF_CHARM))
return;
if (ch->desc) {
send_to_char(ch, "You've got no VNUM to return to, dummy! try 'switch'\r\n");
return;
}
if (ch->desc) {
send_to_char(ch, "You've got no VNUM to return to, dummy! try 'switch'\r\n");
return;
}
one_argument(argument, arg);
@ -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))
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);
while ((k = (struct char_data *) simple_list(GROUP(ch)->members)) != NULL)
if (IN_ROOM(k) == IN_ROOM(ch))
perform_group_gain(k, 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,19 +924,25 @@ 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;
do_assist(tch, GET_NAME(ch), 0, 0);
}
}
/* 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);
hit(ch, FIGHTING(ch), TYPE_UNDEFINED);
if (MOB_FLAGGED(ch, MOB_SPEC) && GET_MOB_SPEC(ch) && !MOB_FLAGGED(ch, MOB_NOTDEADYET)) {
char actbuf[MAX_INPUT_LENGTH] = "";

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

@ -156,6 +156,8 @@ void mobile_activity(void)
{
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)
@ -164,9 +206,7 @@ struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId)
break;
}
}
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)