(Not a hold hand snippet, but all the code required to do this)

Two big reasons for doing this include:

No more kill stealing
No more power leveling

You get out of a fight what you put into it.

In doing this, I also changed how experience works.
No longer, is experience based on difference of levels, it's now based on
level of the mob.
For instance, a level 100 mob will give 500 experience regardless of players
level.  (not quite true, see below)

So, if a level 1 player does 1% of damage to a level 100 mob, they get
exactly that.. 1% of the full experience.
Which would be 5 :)  The other player(s) get 495.

In doing testing of this, I found that players could kill mobs 1-5 levels
below them easier, and faster and get comparable experience, thus leveling
either faster, or nearly as fast.  So, I have added some calculations to
reduce the amount earned as you get higher, never dropping below a certain
point.


As for code, I can share some here, but each mud is different, as is
programming style, and this may or may not work with you, or your mud.

My struct:

struct damage_data
{
   bool valid;  /* for recycling */
   char name[64];  /* the name, nothing to allocate */
   bool NPC;      /* we need NPC's in here. */
   CHAR_DATA *npc;
   unsigned int damage; /* running total */
   int hits;    /* running total of damage hits */
   DAMAGE_DATA *next;
};

rececyle stuff:
DAMAGE_DATA *dam_free;

DAMAGE_DATA *new_damage_data(void)
{
   DAMAGE_DATA dam_zero;
   DAMAGE_DATA *dam;
   if (!dam_free)
     dam = calloc(sizeof(*dam), 1);
   else {
      dam = dam_free;
      dam_free = dam_free->next;
      *dam = dam_zero;
   }
   VALIDATE(dam);
   return dam;
}

void free_damage_data(DAMAGE_DATA *dam)
{
   if (!IS_VALID(dam))
     return;
   dam->next = dam_free;
   dam_free = dam;
   INVALIDATE(dam);
}

in extract_char() add remove_damage_records();

and if it's also an NPC remove_damage_records_others();

/* removes all my damage records once I'm dead */
void remove_damage_records(CHAR_DATA *ch)
{
   DAMAGE_DATA *dam=NULL, *dam_next=NULL, *prev = NULL;
         
   for (dam=ch->damage_data; dam!=NULL;dam = dam_next){
      dam_next = dam->next;
      UNLINK(dam, ch->damage_data, prev);
      free_damage_data(dam);
   }
   ch->damage_data = NULL;
}

/* removes damage records from everyone else that has me in their list */
void remove_damage_records_others(CHAR_DATA *ch)
{
   DAMAGE_DATA *dam=NULL, *dam_next=NULL, *prev = NULL;
   CHAR_DATA *loop;
      
   for (loop=char_list; loop!=NULL; loop=loop->next){
      for (dam=loop->damage_data; dam!=NULL;dam = dam_next){
         dam_next = dam->next;
         if (dam->NPC && dam->npc == ch){
           UNLINK(dam, loop->damage_data, prev);
           free_damage_data(dam);
         }
   
      }
   }
}


In group_gain i do alot of stuff, but for starters:

/* this counts group numbers and adds up total damage to mob, you should
remove the group stuff */
   for (dam = victim->damage_data; dam!=NULL; dam=dam->next){
      if (ch->group && !dam->NPC)
        groupc++;
      dam_total+=dam->damage;
   }


Here's the loop that I use to give out experience. You won't be able to use
this straight out.
      for (dam = victim->damage_data; dam!=NULL; dam=dam->next){
         if (dam->NPC) continue;
         och = get_char_player(ch, dam->name);

         if (!och)  {
            och = str_load_char_offline(dam->name);
            if (!och) /* not existant */
              continue;
            offline=TRUE;
         }
         xp = xp_compute(och, victim);
         /* how much damage done */
         damage = dam_total*100/dam->damage;
         /* let's do the math here */
         exp = xp*100/damage;

         if (groupc>1){ /* only if group is greater than one */
            exp+=(exp*group);
         }
         if (offline) {
            char buf[128];
            if (IS_GHOST(och))
              och->pcdata->odeath_points+=exp;
            else
              och->pcdata->offline_exp+=exp;


           sprintf(buf, "Offline player %s earned %i points in the death of
%s.", och->name, exp, victim->name);
            wiznet(buf, NULL,NULL, WIZ_INFO,0,0);
            log_string(buf);
            save_char_obj(och);
            free_char(och);
            continue;
         }

         /* killing animated zombies reaps no rewards */
         if ( (IS_NPC(victim)) && (victim->pIndexData->vnum ==
MOB_VNUM_ZOMBIE ||
                                   victim->pIndexData->vnum ==
MOB_VNUM_ELEMENTAL ||
                                   victim->pIndexData->vnum ==
MOB_VNUM_GOOD_GUARDIAN||
                                   victim->pIndexData->vnum ==
MOB_VNUM_EVIL_GUARDIAN))
           xp = 0;

         if (och->in_room != victim->in_room){
            sprintf(buf, "{%cYou aided in the death of %s and receive {%c%d
{%c%s point%s.{x\n\r",
                    IS_GHOST(och) ? 'c' : 'r',
                    PERS(victim, och),
                    IS_GHOST(och) ? 'C' : 'R', exp,
                    IS_GHOST(och) ? 'c' : 'r',
                    IS_GHOST(och) ? "death" : "experience", (exp>1)?"s":"");
         }
         else
           sprintf(buf, "{%cYou receive {%c%d {%c%s point%s.{x\n\r",
                   IS_GHOST(och) ? 'c' : 'r',
                   IS_GHOST(och) ? 'C' : 'R', exp,
                   IS_GHOST(och) ? 'c' : 'r',
                   IS_GHOST(och) ? "death" : "experience", (exp>1)?"s":"");

         send_to_char(buf, och);
         if (IS_GHOST(och))
           gain_death(och, exp);
         else{
            gain_exp(och,exp);
         }
         save_char_obj(och);
      }


update_damage_record is called in damage (whenever there is damage)

void update_damage_record(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{   
   DAMAGE_DATA *dam_list;
   /* see if there is a record for this user */
   for (dam_list = victim->damage_data; dam_list!=NULL;
dam_list=dam_list->next){
         
      if (!strcmp(ch->name, dam_list->name)) {/* found it */
         dam_list->damage+=dam;
         dam_list->hits++;
         if (IS_NPC(ch)){
            if (ch->leader!=NULL){
               if (!IS_NPC(ch->leader))
                 update_damage_record(ch->leader, victim, dam);
            }
            else if (ch->master!=NULL){
               if (!IS_NPC(ch->master))
                 update_damage_record(ch->leader, victim, dam);
            }
         }
         return;
      }
   }
   /* didn't find an entry, add a new one */
   dam_list = new_damage_data();
   
   if (IS_NPC(ch)){
      dam_list->NPC = TRUE;
      dam_list->npc = ch;
   }
   else{
      dam_list->NPC = FALSE;
      dam_list->npc = NULL;
   }
   strcpy(dam_list->name, ch->name);
   dam_list->hits=1;
   dam_list->damage=dam;

   dam_list->next = victim->damage_data;
   victim->damage_data=dam_list;

   if (IS_NPC(ch)){
      if (ch->leader!=NULL){
         if (!IS_NPC(ch->leader))
           update_damage_record(ch->leader, victim, dam);
      }
      else if (ch->master!=NULL){
         if (!IS_NPC(ch->master))
           update_damage_record(ch->leader, victim, dam);
      }
   }
}


Cute little imm command to show you who has damaged who and how much:
void do_damage(CHAR_DATA *ch, char *argument)
{
   DAMAGE_DATA *dam=NULL;
   CHAR_DATA *loop;
   int count=0, count2=0;
   printf_to_char(ch, "{gDamage data:\n");
   printf_to_char(ch, "{w============\n");

   for (loop=char_list; loop!=NULL; loop = loop->next){
      if (loop->damage_data==NULL) continue;
      count++;
      printf_to_char(ch, "{g%s:\n", loop->name);
      for (dam = loop->damage_data; dam!=NULL; dam=dam->next){
         printf_to_char(ch, "\t{w%-20s    Damage:  %4i   Hits: %4i\n\r",
                        (dam->NPC)?dam->npc->name:dam->name, dam->damage,
dam->hits);
         count2++;
      }
      printf_to_char(ch, "\n");
   }
   printf_to_char(ch, "\n{W%i {wrecords from {W%i {wcharacters.\n", count,
count2);
}


That's it... Have fun.

Jason

-----Original Message-----
From: Michael Gerner Andreasen [mailto:[EMAIL PROTECTED]
Sent: Tuesday, August 13, 2002 4:49 AM
To: rom list
Subject: Fw: Idea about new exp system



----- Original Message -----
From: "Michael Gerner Andreasen" <[EMAIL PROTECTED]>
To: "Jason Gauthier" <[EMAIL PROTECTED]>
Sent: Tuesday, August 13, 2002 10:47 AM
Subject: Re: Idea about new exp system


> > A little late, as I've been on vacation.
> Np.
>
> > This is very close to, if not exactly what I've implemented.
> Good, now i know atleast one other person who likes the idea.
>
> > (I save the damage and tally it for each unique attacker)
> > Then you divide it up, and give the percentages.
> The same plan here.
>
> > But adding up total damage, if the mob is wrathed, or heals, you get an
> > accurate percentage.
> Thats true, wants it to be fair of all.
>
> > One caveat is with pets.  If an NPC does damage and has no master, I
don't
> > update/add anything.
> > Otherwise, it's master gets the credit.
> Ahh nice dident think of this, but then again, i only got stuff on paper
at
> the moment,
> can see the picture, but the hands are still.
>
> Would you like to share some code, with the rest of us?  would like to see
> loops for updating in healing and exp gains.
>
> and any info on linked lists would be help full, as it is not what I
> normally play with all day long.
>
> will send some code to the list, as I get stuff coded, will properly be
full
> of bugs and what not, but atleast iam trying something new.
>
> and to make ppl on the list happy, iam gona try pass this mail via the
spell
> checker...
> That spell checker didn't complete, but I hope you can read it anyways.
>
> -- Kawaki
>

-- 
ROM mailing list
[email protected]
http://www.rom.org/cgi-bin/mailman/listinfo/rom

Reply via email to