SWR installcybernetics code error

Posted by Jason on Fri 24 Mar 2006 09:47 PM — 20 posts, 67,113 views.

#0
I'm currently installing a code for player installed cybernetics...when it was a command it worked fine.. now it is crashing when i turned it into a skill and added a the timer. I marked where it is crashing in the code with a ---->

                chance = IS_NPC(ch) ? ch->top_level : (int) (ch->pcdata->learned[gsn_surgery]);
                if ( number_percent( ) < chance )
                {
                   send_to_char( "&GYou begin the long process of installing a cybernetic part.\n\r", ch);
                   act( AT_PLAIN, "$n takes $s scalpel and begins to preform the surgery.", ch, NULL, argument , TO_ROOM );
                   add_timer ( ch , TIMER_DO_FUN , 1 , do_installcybernetic , 1 );
                   ch->dest_buf   = str_dup(arg1);
                   return;
                }
                send_to_char("&RYou can't figure out how to preform surgery.\n\r",ch);
                learn_from_failure( ch, gsn_surgery );
                return;

        case 1:
                if ( !ch->dest_buf )
                 return;
                strcpy(arg1, ch->dest_buf);
                DISPOSE( ch->dest_buf);
                break;

        case SUB_TIMER_DO_ABORT:
                DISPOSE( ch->dest_buf );
                ch->substate = SUB_NONE;
                send_to_char("&RYou are interupted and fail to finish your work.\n\r", ch);
                return;
    }

    ch->substate = SUB_NONE;
    if ( ms_find_obj(ch) )
	return;

    obj = get_obj_carry( ch, arg1 );
    chance = IS_NPC(ch) ? ch->top_level : (int) (ch->pcdata->learned[gsn_surgery]) ;

    if ( number_percent( ) < chance  )
    {
       send_to_char( "You realize that you installed the cybernetic part upside down and crossed some wires.", ch);
       learn_from_failure( ch, gsn_surgery );
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
       return;
    }

    
    if (obj->item_type == ITEM_COMMCYBER)
    {
---->  if (!IS_SET(victim->pcdata->cyber, CYBER_COMM))
       {
          send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
          return;
       }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
       SET_BIT (victim->pcdata->cyber, CYBER_COMM );
    }

USA #1
Use gdb to print a backtrace.

Make sure it's not checking NPCs either.
#2
i have and here is the message:

#0 0x08161db1 in do_installcybernetic (ch=0x851e448, argument=0x81880dc "")
at medical.c:168
#1 0x080b60ff in violence_update () at fight.c:261
#2 0x08125ddc in update_handler () at update.c:2301
#3 0x0809d105 in game_loop () at comm.c:576
#4 0x0809c578 in main (argc=7, argv=0xbfffde84) at comm.c:241
USA #3
Where does the 'victim' pointer come from? It looks like you never set it, but you'll need to do that if you want this to work -- you can't dereference victim without setting it first. Also make sure as Zeno pointed out that you don't let it consider NPCs otherwise it will crash because they have no pcdata member.
#4
ok here is the whole code so if you can find the problem cause i can't

void do_installcybernetic( CHAR_DATA * ch, char *argument )
{
    CHAR_DATA *victim;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *holdscalpel;
    OBJ_DATA *obj;
    bool checkcyber;
    checkcyber = FALSE;
    int chance;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    switch( ch->substate )
    {
	default:
    if ( arg1[0] == '\0' )
    {
	send_to_char( "Install what?\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	send_to_char( "In who?\n\r", ch );
	return;
    }
    if( IS_NPC( ch ) )
      return;

    if( ( victim = get_char_room( ch, arg2 ) ) == NULL )
    {
      send_to_char( "They aren't here.\n\r", ch );
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "You can't install cybernetic parts in NPC's!\n\r", ch );
      return;
    }

    if( IS_IMMORTAL( victim ) )
    {
      send_to_char( "Don't try to install cybernetic parts on immortals.\n\r", ch );
      return;
    }

    if( ch == victim )
    {
      send_to_char( "You can't install cybernetics yourself!\n\r", ch );
      return;
    }
	holdscalpel = get_eq_char ( ch, WEAR_HOLD );
      if( holdscalpel && !( holdscalpel->item_type == ITEM_SCALPEL ) )
	holdscalpel = NULL;

    if( !holdscalpel )
    {
      send_to_char( "You need to be holding a scalpel to preform this surgery.\n\r", ch );
      return;
    }

/*    if (ch->pcdata->maxcybers == ch->pcdata->cybers )
    {
	send_to_char( "This person can't take any more cybernetics and stay human\n\r", ch );
	return;
    }*/


     for ( obj = ch->last_carrying; obj; obj = obj->prev_content )     
     {
       if (obj->item_type == ITEM_EYECYBER || obj->item_type == ITEM_COMMCYBER ||
	   obj->item_type == ITEM_LEGCYBER || obj->item_type == ITEM_CHESTCYBER ||
	   obj->item_type == ITEM_REFLEXCYBER || obj->item_type == ITEM_MINDCYBER ||
	   obj->item_type == ITEM_STRCYBER || obj->item_type == ITEM_REACTORCYBER)
	     checkcyber = TRUE;
     }
	if ( !checkcyber )
        {
          send_to_char( "&RYou don't seem  to have a cybernetic part right now.\n\r", ch);
          return;
        }

	if ( !xIS_SET(ch->in_room->room_flags, ROOM_OPERATINGROOM) )
	{
	    send_to_char ("&R You need to be in an operating room to do this proceedure.\n\r", ch );
	    return;
	}
                chance = IS_NPC(ch) ? ch->top_level : (int) (ch->pcdata->learned[gsn_surgery]);
                if ( number_percent( ) < chance )
                {
                   send_to_char( "&GYou begin the long process of installing a cybernetic part.\n\r", ch);
                   act( AT_PLAIN, "$n takes $s scalpel and begins to preform the surgery.", ch, NULL, argument , TO_ROOM );
                   add_timer ( ch , TIMER_DO_FUN , 1 , do_installcybernetic , 1 );
                   ch->dest_buf   = str_dup(arg1);
                   return;
                }
                send_to_char("&RYou can't figure out how to preform surgery.\n\r",ch);
                learn_from_failure( ch, gsn_surgery );
                return;

        case 1:
                if ( !ch->dest_buf )
                 return;
                strcpy(arg1, ch->dest_buf);
                DISPOSE( ch->dest_buf);
                break;

        case SUB_TIMER_DO_ABORT:
                DISPOSE( ch->dest_buf );
                ch->substate = SUB_NONE;
                send_to_char("&RYou are interupted and fail to finish your work.\n\r", ch);
                return;
    }

    ch->substate = SUB_NONE;
    if ( ms_find_obj(ch) )
	return;

    obj = get_obj_carry( ch, arg1 );
    chance = IS_NPC(ch) ? ch->top_level : (int) (ch->pcdata->learned[gsn_surgery]) ;

    if ( number_percent( ) < chance  )
    {
       send_to_char( "You realize that you installed the cybernetic part upside down and crossed some wires.", ch);
       learn_from_failure( ch, gsn_surgery );
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
       return;
    }
#5
here is the rest of it


  if ( number_percent ( ) > chance)
  {  
    if (obj->item_type == ITEM_COMMCYBER)
    {
       if (!IS_SET(victim->pcdata->cyber, CYBER_COMM))
       {
          send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
          return;
       }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
       SET_BIT (victim->pcdata->cyber, CYBER_COMM );
    }

    else if (obj->item_type == ITEM_EYECYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_EYES))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
            return;
        }
        SET_BIT (victim->pcdata->cyber, CYBER_EYES );
        victim->affected_by   = AFF_INFRARED;
    }
    else if (obj->item_type == ITEM_LEGCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_LEGS))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_LEGS );
        victim->max_move += number_range ( 200 , 500 );
    }
    else if (obj->item_type == ITEM_CHESTCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_CHEST))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_CHEST );
    }
    else if (obj->item_type == ITEM_REFLEXCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_REFLEXES))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_REFLEXES );
    }
    else if (obj->item_type == ITEM_REACTORCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_REACTOR))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_REACTOR );
    }
    else if (obj->item_type == ITEM_MINDCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_MIND))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_MIND );
    }

    else if (obj->item_type == ITEM_STRCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_STRENGTH))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_STRENGTH );
    }
    
    send_to_char( "&GYou finish your surgery and sew up your patient.&w\n\r", ch);
    act( AT_PLAIN, "$n finishes $s surgery.", ch,
         NULL, argument , TO_ROOM );

    
         long xpgain;

         /*xpgain = UMIN( obj->cost*100 ,
            ( exp_level(ch->skill_level[MEDICAL_ABILITY]+1) -
              exp_level(ch->skill_level[MEDICAL_ABILITY]) ) );*/
	 xpgain = 3000;
         gain_exp(ch, xpgain, MEDICAL_ABILITY);
         ch_printf( ch , "You gain %d medical experience.", xpgain );
    
        learn_from_success( ch, gsn_surgery );
  }   
}
USA #6
Print victim, then victim->pcdata, then victim->pcdata->cyber for me.
#7
(gdb) p victim
$2 = (CHAR_DATA *) 0x812293d
(gdb) p victim->pcdata
$3 = (PC_DATA *) 0xffeff085
(gdb) p victim->pcdata->cyber
Cannot access memory at address 0xffeff0cd

hmmmm why is cyber null here?
USA #8
Crashing when you added the skill and timer? That doesn't seem to be the problem. Check to make sure the cyber field is coded correctly.
#9
it has to be... i mean it worked just fine before i made it a skill with a timer... i tested it untill it did work
USA #10
Well then paste the working code here, and I'll compare it to the non-working.
#11

void do_installcybernetic( CHAR_DATA * ch, char *argument )
{
    CHAR_DATA *victim;
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *holdscalpel;
    OBJ_DATA *obj;
    bool checkcyber;
    checkcyber = FALSE;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Install what?\n\r", ch );
	return;
    }

    if ( arg2[0] == '\0' )
    {
	send_to_char( "In who?\n\r", ch );
	return;
    }
    if( IS_NPC( ch ) )
      return;

    if( ( victim = get_char_room( ch, arg2 ) ) == NULL )
    {
      send_to_char( "They aren't here.\n\r", ch );
      return;
    }

    if( IS_NPC( victim ) )
    {
      send_to_char( "You can't install cybernetic parts in NPC's!\n\r", ch );
      return;
    }

    if( IS_IMMORTAL( victim ) )
    {
      send_to_char( "Don't try to install cybernetic parts on immortals.\n\r", ch );
      return;
    }

    if( ch == victim )
    {
      send_to_char( "You can't install cybernetics yourself!\n\r", ch );
      return;
    }
	holdscalpel = get_eq_char ( ch, WEAR_HOLD );
      if( holdscalpel && !( holdscalpel->item_type == ITEM_SCALPEL ) )
	holdscalpel = NULL;

    if( !holdscalpel )
    {
      send_to_char( "You need to be holding a scalpel to preform this surgery.\n\r", ch );
      return;
    }

/*    if (ch->pcdata->maxcybers == ch->pcdata->cybers )
    {
	send_to_char( "This person can't take any more cybernetics and stay human\n\r", ch );
	return;
    }*/


     for ( obj = ch->last_carrying; obj; obj = obj->prev_content )     
     {
       if (obj->item_type == ITEM_EYECYBER || obj->item_type == ITEM_COMMCYBER ||
	   obj->item_type == ITEM_LEGCYBER || obj->item_type == ITEM_CHESTCYBER ||
	   obj->item_type == ITEM_REFLEXCYBER || obj->item_type == ITEM_MINDCYBER ||
	   obj->item_type == ITEM_STRCYBER || obj->item_type == ITEM_REACTORCYBER)
	     checkcyber = TRUE;
     }
	if ( !checkcyber )
        {
          send_to_char( "&RYou don't seem  to have a cybernetic part right now.\n\r", ch);
          return;
        }

	if ( !xIS_SET(ch->in_room->room_flags, ROOM_OPERATINGROOM) )
	{
	    send_to_char ("&R You need to be in an operating room to do this proceedure.\n\r", ch );
	    return;
	}
     if ( ms_find_obj(ch) )
	return;

    obj = get_obj_carry( ch, arg1 );
    if (obj->item_type == ITEM_COMMCYBER)
    {
       if (IS_SET(victim->pcdata->cyber, CYBER_COMM))
       {
          send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
          return;
       }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
       SET_BIT (victim->pcdata->cyber, CYBER_COMM );
    }

    else if (obj->item_type == ITEM_EYECYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_EYES))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
            return;
        }
        SET_BIT (victim->pcdata->cyber, CYBER_EYES );
        victim->affected_by   = AFF_INFRARED;
    }
    else if (obj->item_type == ITEM_LEGCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_LEGS))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_LEGS );
        victim->max_move += number_range ( 200 , 500 );
    }
    else if (obj->item_type == ITEM_CHESTCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_CHEST))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_CHEST );
    }
    else if (obj->item_type == ITEM_REFLEXCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_REFLEXES))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_REFLEXES );
    }
    else if (obj->item_type == ITEM_REACTORCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_REACTOR))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_REACTOR );
    }
    else if (obj->item_type == ITEM_MINDCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_MIND))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_MIND );
    }

    else if (obj->item_type == ITEM_STRCYBER)
    {
        if (IS_SET(victim->pcdata->cyber,CYBER_STRENGTH))
        {
            send_to_char( "&RThey seem to already have that cybernetic part installed.\n\r", ch);
             return;
        }
       checkcyber = TRUE;
       separate_obj( obj );
       obj_from_char( obj );
       extract_obj( obj );
        SET_BIT (victim->pcdata->cyber, CYBER_STRENGTH );
    }
      
}
USA #12
While I look at this, here's an initial question. The code returns if ch is a NPC. But later on you have this:
                chance = IS_NPC(ch) ? ch->top_level : (int) (ch->pcdata->learned[gsn_surgery]);

Why bother to check IS_NPC if you know that it already isn't?
#13
and it wasn't the ! infront of the line... I noticed it and fixed it... still it crashed
Canada #14
Bleh. You do understand how skill timers work in stock Smaug, right? What it does is call the function, run through until it reaches the add_timer, then when the timer expires, it calls the function again.

Now, the way it keeps from repeating the same thing over and over again is by changing the char's substate to a different value. Then, it calls a switch statement based on substate to see what it should do.

In your default case, you have the checks to allocate the victim and the cybernetic part itself. You also set the first argument to a pointer on the ch (dest_buf), to be stored for later use.

Now, when the timer is called again, it is calling the function with no argument. Since the char's substate is 1, the first thing it sees is to set the new arg1 to the char's dest_buf. This is the argument it used to find the original object, so now the cybernetic part you're installing is defined.

All well and good.

However, arg2 (the victim's name) was NOT stored in the timer. Since the timer executes your function simply as installcybernetic, rather than something like installcybernetic eye simon, therefore there is no pointer allocated to the victim.

In short, what you'll need to do is assign the victim's name (or char_data) to a pointer on the installer, such as ch->installing. (NOT pcdata->installing, as you seem to have this useable for NPCs). Then, you'll need to save and reload this much as you've done for the obj (dest_buf/arg1), then perform another get_char_room on the vict to make sure he hasn't wandered off/been killed/e.t.c, to prevent another crash.

Cheers! :)
Amended on Sat 25 Mar 2006 06:55 AM by Dace K
USA #15
What Dace said. You're not storing the victim, and so when the timer triggers the code crashes because it does not know who the victim is.

You do however store arg1 and get the object from there, so it should be quite simple to see how to store the victim as well.
Canada #16
*cough*. I suppose that's a shorter way of saying it :D
#17
ok it may be the fact that i just woke up but i don't see where i would store it
Canada #18
Read my post on page 1. Store arg2 the same place and way you stored arg1.
#19
yeah i figured it out....Like i said cause i started working before i actually woke up LOL. And it works now WOO HOO thanx for the help guys... It is always something stupid i swear