Identical object wear prevention

  • Sapphire
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
7 months 3 days ago #8056 by Sapphire
Identical object wear prevention was created by Sapphire
I'm looking for information on a check to identify if a character is already wearing an instance of an item. In my case, I want to allow common items to have duplicates worn by a character, but items that are powerful to be considered unique and for the game to allow only a single instance of this item to be used before it sends a message like, "You are already using that item," to be sent back to the char when they try to equip it in any slot.

I'm looking at the perform_wear function in act.item.c as the main insertion point for this code, and I know it would need to come prior to any of the equip_char type deals in that function. I also have an object flag set up to identify these, "Power," pieces, but I can't figure out how to identify if a char is already wearing it.

So, let's say I create a very nice weapon, but I have a dual-wielding class (I do), I don't want that player to be able to wield multiple instances of The Sword of TBA Awesomeness.

if ((OBJ_FLAGGED(obj, ITEM_POWER_EQ)) && (not sure what to put here to check for obj's vnum against if player has an instance of that object vnum worn)) {
send_to_char(ch, "You already have one of those equipped.\r\n");
return;
}

Please Log in or Create an account to join the conversation.

  • lacrc
  • lacrc's Avatar
  • Away
  • Senior Boarder
  • Senior Boarder
More
7 months 3 days ago - 7 months 3 days ago #8058 by lacrc
Replied by lacrc on topic Identical object wear prevention
Well you can use the GET_OBJ_VNUM(obj) macro to get an object's vnum, and the GET_EQ(ch, pos) macro to get the currently equipped item in a certain slot. But I suppose you would only need to check in case of weapons, rings, necklaces and wrists (which are the only WEARs that have two slots).

A simple solution for you would look something like this in perform_wear() in act.item.c:
    if ((where == WEAR_DWIELD) || (where == WEAR_FINGER_L) ||
            (where == WEAR_NECK_2) || (where == WEAR_WRIST_L)) {
        if (GET_EQ(ch, where - 1) && GET_OBJ_VNUM(GET_EQ(ch, where - 1)) == GET_OBJ_VNUM(obj)) {
            send_to_char(ch, "You already have one of those equipped.\r\n");
            return;
        }
    }
That is, when a character tries to equip an item on a 2nd slot you then check the first slot to see if the VNUMs are the same, and act accordingly.
This is assuming that your dual wield wear flag is called WEAR_DWIELD, and that you kept the stock flags that declared left slots after right slots (ie. WEAR_FINGER_L == 1 + WEAR_FINGER_R). If that isn't the case then you need to do some adjustments! :)

But that doesn't cover the case of the items that can be used in two different kinds of WEARs, like a ring necklace that can be worn as a neck or ring (or even other like and item and that be a weapon or a shield maybe?).
For those cases you would need to loop through all equipped gear and check those vnums, something like:
    for (i = 0; i < NUM_WEARS; i++) {
        if (GET_EQ(ch, i) && GET_OBJ_VNUM(GET_EQ(ch, i)) == GET_OBJ_VNUM(obj)) {
            send_to_char(ch, "You already have one of those equipped.\r\n");
            return;
        }
    }
Hmm, this one actually turned out to be simpler looking than the one above, oh well!
Anyways, I haven't tested any of those so beware! Hope it helps! :)
Last edit: 7 months 3 days ago by lacrc.
The following user(s) said Thank You: Chime

Please Log in or Create an account to join the conversation.

  • Sapphire
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
7 months 3 days ago #8059 by Sapphire
Replied by Sapphire on topic Identical object wear prevention
Lacrc, your fix worked flawlessly as a drag and drop into the code. I updated it to include a check for my unique type power weapon object code, but it worked globally as a check for duplicate items. Thank you for helping me with this, I'm very appreciative!

Please Log in or Create an account to join the conversation.

  • lacrc
  • lacrc's Avatar
  • Away
  • Senior Boarder
  • Senior Boarder
More
7 months 3 days ago #8060 by lacrc
Replied by lacrc on topic Identical object wear prevention
Glad to help! And sorry about the check for the flag, completely forgot about that kinda important thing heh
Just a question, which one did you use? The first one or the one with loop?
The following user(s) said Thank You: Sapphire

Please Log in or Create an account to join the conversation.

  • Sapphire
  • Topic Author
  • Offline
  • Fresh Boarder
  • Fresh Boarder
More
7 months 2 days ago #8062 by Sapphire
Replied by Sapphire on topic Identical object wear prevention
Lacrc, I used the 2nd code snippet you mentioned and modified it with and additional check for our UNIQUE_ITEM flag. In addition to this, an, "int i;" insertion at the beginning of the function was required. I inserted this check prior to any other checks included in the code so that it checks for duplicate uniques prior to anything else.

I tested this code and found that it performed exactly as I desired without any issues. It prevented me from wearing duplicate uniques, but it allowed me to continue to wear duplicate non-uniques. Additionally, this performed as I had hoped in that it was a global check for all player eq slots (Rings, neck, ears, wield, hold).

I included a bit of the code here for you to see, starting at the beginning of the void function.
void perform_wear(struct char_data *ch, struct obj_data *obj, int where)
{
	int i;
  /*
   * ITEM_WEAR_TAKE is used for objects that do not require special bits
   * to be put into that position (e.g. you can hold any object, not just
   * an object with a HOLD bit.)
   */

  int wear_bitvectors[] = {
    ITEM_WEAR_TAKE, ITEM_WEAR_FINGER, ITEM_WEAR_FINGER, ITEM_WEAR_NECK,
    ITEM_WEAR_NECK, ITEM_WEAR_BODY, ITEM_WEAR_HEAD, ITEM_WEAR_LEGS,
    ITEM_WEAR_FEET, ITEM_WEAR_HANDS, ITEM_WEAR_ARMS, ITEM_WEAR_SHIELD,
    ITEM_WEAR_ABOUT, ITEM_WEAR_WAIST, ITEM_WEAR_WRIST, ITEM_WEAR_WRIST,
    ITEM_WEAR_WIELD, ITEM_WEAR_TAKE, ITEM_WEAR_EAR, ITEM_WEAR_EAR, ITEM_WEAR_MASK
  };

  const char *already_wearing[] = {
    "You're already using a light.\r\n",
    "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
    "You're already wearing something on both of your ring fingers.\r\n",
    "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
    "You can't wear anything else around your neck.\r\n",
    "You're already wearing something on your body.\r\n",
    "You're already wearing something on your head.\r\n",
    "You're already wearing something on your legs.\r\n",
    "You're already wearing something on your feet.\r\n",
    "You're already wearing something on your hands.\r\n",
    "You're already wearing something on your arms.\r\n",
    "You're already using a shield.\r\n",
    "You're already wearing something about your body.\r\n",
    "You already have something around your waist.\r\n",
    "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
    "You're already wearing something around both of your wrists.\r\n",
    "You're already wielding a weapon.\r\n",
    "You're already holding something.\r\n",
    "YOU SHOULD NEVER SEE THIS MESSAGE.  PLEASE REPORT.\r\n",
    "You're already wearing something in both ears.\r\n",
    "You're already wearing something as a mask.\r\n"
  };
  /* lacrc from TBAMud Forums credits for core code, modified for uniques: Duplicate/Unique wear prevention */
    for (i = 0; i < NUM_WEARS; i++) {
        if (GET_EQ(ch, i) && (OBJ_FLAGGED(obj, ITEM_UNIQUE)) && GET_OBJ_VNUM(GET_EQ(ch, i)) == GET_OBJ_VNUM(obj)) {
            send_to_char(ch, "You already have one of those equipped.\r\n");
            return;
        }
    }
  /* first, make sure that the wear position is valid. */
  if (!CAN_WEAR(ch, obj, wear_bitvectors[where])) {
    act("You can't wear $p there.", FALSE, ch, obj, 0, TO_CHAR);
    return;
  }
  /* for neck, finger, and wrist, try pos 2 if pos 1 is already full */
  if ((where == WEAR_FINGER_R) || (where == WEAR_NECK_1) || (where == WEAR_WRIST_R) || (where == WEAR_EAR_R))
    if (GET_EQ(ch, where))
      where++;
The following user(s) said Thank You: lacrc

Please Log in or Create an account to join the conversation.

More
6 months 2 weeks ago #8089 by rudeboyrave
Replied by rudeboyrave on topic Identical object wear prevention
Here is a litte trigger we use to prevent players from wearing or even having two Obama Phones.

Name: 'OBAMA PHONE DRONE!', VNum: [22757], RNum: [ 2399]
Trigger Intended Assignment: Objects
Trigger Type: Get Wear , Numeric Arg: 100, Arg list: None
Commands:

while %i% < 30
eval item %actor.eq(%i%)%
if %item.vnum% == 15380
%send% %actor.name% You notice a drone flying high above you!
%send% %actor.name% The surveilance drone targets your spare phone and destroys it!
%echoaround% %actor% %actor.name% attempts to foil the government by obtaining two obama phones! A drone shows up and destroys the device!
odamage %actor% 10000
%purge% %self%
end
eval i %i%+1
done

CyberASSAULT
www.cyberassault.org
cyberassault.org 11111
A post-apocalyptic, sci-fi MUD.

Please Log in or Create an account to join the conversation.

Time to create page: 1.810 seconds