Jump to content
The Dark Mod Forums

Two Player Characters


Recommended Posts

Just played the new Thief 2 FM Among Two Storms. In this you play two characters and can switch between them. This provided fascinating extra gameplay where each player character co-operated to help the other. I really enjoyed this one. Imagine the following (NOT the above Thief FM)

 

Two player characters: Hackett and Freeman are to rob an old Bafford style castle. Freeman needs to get in to the lower courtyard but is faced with a guarded locked portcullis lit by torches. He has no water arrows. Hackett starts on a nearby village roof and climbs up to an open window overlooking the front gate area and he puts out the torches with water arrows. He climbs through the window and throws the gate lever to allow Freeman to slip in.

 

The player now switches to play Freeman, gets inside to the courtyard. Hackett above at an inner window is trapped and has no ropes. Freeman has ropes but is not in position to place one for Hackett to directly climb down. Instead he shoots one up through an open window to a beam. Hackett in that room retrieves the rope arrow and goes to another window where he can rope down to a garden.

 

Meanwhile Freeman is spotted by a guard and after a fight in which he is badly injured he escapes over a low wall. Here Hackett gives him or places a health potion through a barred window in the garden wall for Freeman to retrieve on the other side. And so on. You need to the character you switch from in a safe place in shadow etc.

 

Could we implement something like this in Dark Mod?

 

In Thief, each player has his own inventory using a special script. I think we would need special code in Dark Mod. Maybe it could be done in script. By 'inventory' I also mean weapons/ammo etc. Let's imagine a simple method then wonder later how:

 

 


  •  
  • Two thief AI entities to represent the two pcs, initially stored in a blue room.
  • Two inventories stored, one on each pc.
  • Player starts as say Freeman (pc1) so pc1 AI is kept in blue room and his inventory transferred to the player.
  • Hackett (pc2) is teleported to the start point.
  • A simple switch is put in the inventory to toggle a script. We already have this.
  • When the player wants to switch then:
  • He is teleported to the other position and the two pc AIs are teleported to/from the blue room and the inventories swapped about.

 

The main problem is the inventory. Perhaps one day there could be code to implement this. I'm sure the code was originally designed so each AI can have an inventory but I think it is unusable at present. I don't know.

 

Another problem is we need an AI stealth mode so the other pc can stay hidden, will not attack enemy unless he is attacked first. Might be done using a team that is set neutral to others but regarded as enemy by them. This is already possible. On alert that relationship could be changed temporarily or possibly we want the pc to run away?

Link to post
Share on other sites

There's a custom script function to put things into inventory (which you already know about). It would (I believe) be just as easy, using the same model in reverse, to make a function to take things out of inventory and move them inside target brushes. And I believe there's a function that returns all the items in the inventory too.

 

So the player-swap script could save all the inventory items as parameters somewhere, move them out, then move-in the saved inventory items from the last swap (except for the very first swap, in which case it moves in a pre-selected inventory for player2.)

 

I agree there's some good gameplay potential here. It reminds me of some books and movies that use this technique, following different characters independently, each one adding a new angle to the same story (Left Bank Gang, Rashomon). Not to mention some classic adventure games (Manic Mansion, etc.) I think you could be really creative to how they could interact too, and how their perspective could be different.

What do you see when you turn out the light? I can't tell you but I know that it's mine.

Link to post
Share on other sites

mmm... This got me looking at our script events but I can't see anything to return the inventory contents. There are several functions for known entities, eg, remove entity99 but you need to know that entity99 is in the inventory. So say the player picks up a health potion I can't see how script can detect that. I do see a function that can store an inventory on any other AI (or any entity come to that) but not a function to copy whole inventories to another entity which would be ideal. Would still need to test this gets saved with a gamesave too.

Link to post
Share on other sites

In the source code there's ../Darkmod/Inventory/inventory.cpp.

Everything you want to do I think can be done in here, modifying a few things, or possibly using the same functions in a script (some functions can be used in scripts and some can't; but it's worth trying).

 

Edit: Looking back over it, I may have no idea what I'm talking about in the rest of this post. So I guess my main point is just, try browsing around in the source code in places like the darkmod/inventory folder for ideas about how things work. I'll keep what I wrote before though, for the record. Just my first impression looking through it.

 

 

First, there seems to be a way to set an owner to inventory items:

 

void CInventory::SetOwner(idEntity *owner)
{
m_Owner = owner; 

for (int i = 0; i < m_Category.Num(); i++)
{
	m_Category[i]->SetOwner(owner);
}
}

 

But you still have to fix a way in the code to switch which owner appears in the .gui. I think it would be as easy as an "if owner = 'player1'...".

 

Actually, scratch that. I think that's looking for a literal entity that's a player (player 2). What you want is a bogey variable to stand in for 2 virtual players (sharing the same $player1 entity), so you'd create your own variable "virtual_owner", then in the parts of the .gui code where you scroll through the inventory, only make the inventory items show for that player. To do that... first

 

I believe there is a way to scroll through the inventory, e.g., to get the number of items for every category is with this variable:

 

int	CInventory::GetNumCategories() const
{
return m_Category.Num();
}

 

Used something like this:

   for(i = 0; i < m_Category.Num(); i++)
{
	m_Category[i]->GetInventory(broadheads, water, rope, etc...);
}

 

Which displays the inventory items for each category in that part of the code.

 

Now with your bogey variable you can just add a little part to this code like

IF player1_playing 
 { 
    IF ( virtual_owner == 1 ) 
       { show inventory item } 
 }
ELSE
 {
    IF ( virtual_owner == 2 ) 
       { show inventory item } 
 }

 

Or something like that. Anyway, that's how you might approach it in the source code.

If you want to do it all in a script, explore

for(i = 0; i < m_Category.Num(); i++)
 {
   m_Category[i]-> [some variable]
 }

as the source code uses it as a way to scroll through the inventory items sequentially, and do things with each one down the list, like save them as a parameter somewhere to restore later.

 

On that note, the restore function for inventory is instructive:

 

void CInventory::Restore(idRestoreGame *savefile)
{
// Clear all member variables beforehand 
Clear();

m_Owner.Restore(savefile);

int num;
savefile->ReadInt(num);
for(int i = 0; i < num; i++) {
	CInventoryCategoryPtr category(new CInventoryCategory(this, ""));

	category->Restore(savefile);
	m_Category.Append(category);
}

savefile->ReadInt(m_LootItemCount);
savefile->ReadInt(m_Gold);
savefile->ReadInt(m_Jewelry);
savefile->ReadInt(m_Goods);
savefile->ReadInt(m_HighestCursorId);

savefile->ReadInt(num);
for(int i = 0; i < num; i++) {
	CInventoryCursorPtr cursor(new CInventoryCursor(this, 0));

	cursor->Restore(savefile);
	m_Cursor.Append(cursor);
}
}

What do you see when you turn out the light? I can't tell you but I know that it's mine.

Link to post
Share on other sites

This is how I did it in Among Two Storms. I know Dark Mod is considerably different, but it might provide some ideas.

 

There are two thief AIs with their team set to Good, and aggressiveness set to 'Ignore until attacked'. This way they won't attack the player, and won't attack any enemies unless they are threatened.

 

Frobbing the 'switch to character' item in the inventory sends a custom stim to the player, based on the character you want to switch to (GarrettStim and PalmerStim). The avatar has receptrons for both stims. They teleport a special marker to the player's current location, teleport out the AI that was representing the other character, and teleport the player to that AI's location.

 

For the inventory swapping I used Telliamed's TrapContainer script. Two markers with this script were linked to the starting point (CD). A TurnOff would move all the items that had '~Contained' links to the player to the trap itself. A TurnOn would create 'Contained' between the player and all the items currently contained in the trap. Managing the inventories became a matter sending the correct TurnOn and TurnOff messaged to these scripts at the correct time.

 

Hope this helps.

Link to post
Share on other sites

Ah hello Haplo - I'd forgotten you were a member here. Yes, that temporary invisible marker sounds important else you'd see the other AI model for a fraction of a second when teleporting until it was teleported away. We can do the same with an invisible non solid entity.

 

The main problem seems to be the inventory. I'm not knowledgeable enough in C++ and even my scripting is not very advanced but if I could see a suitable script event that returns inventory contents I could probably do it.

 

There is one I think that returns the 'current' inventory item. I don't know if that has to be actually visibly selected in the hud. It might just mean a pointer to the last item selected even if it is no longer visible. In which case one could get that and presumably the inventory would automatically increment its 'curren't item. So you could then repeat until the inventory is empty copying them all into an inventory on one of the pc entities. Just needs time to try that.

 

Problem is I keep getting interested in new ideas but have to stay focused on finishing my own FM first. So this is mainly an interesting thought experiment at the moment.

Link to post
Share on other sites

Removing the inventory items one by one might have the undesirable effect of all the items quickly scrolling on the screen every time the character is changed. Depends on how fast it can be done in TDM.

 

Does TDM have the concept of links? Similar to the Contains links between the player and objects? If so you could loop through all the links and reassign them to some invisible chest.

 

In addition to all of these, there are many little details that need taking care of. For example, I could not set up a loot objective because there were two inventories and therefore two stacks of loot. Dark Engine did not add them up. I could not set up the objective using QVars, because there are no QVars that hold the amount of loot stolen. The QVar TOTAL_LOOT is only calculated at the end of the mission. (That is why in-game shops are SO much work in Dark Engine; you'd have to add a custom stim to each loot object and count them that way).

 

The final stats window showed the wrong loot value too, because it showed the loot of the character you played with the last. Therefore, on detection of the mission ending, I had to quickly combine the two inventories. You probably noticed it just before the mission ended.

 

 

Edited by Haplo
Link to post
Share on other sites

Yes I wondered about all the items flashing up on screen especially if it is a big inventory. My guess is that in the code the entire inventory is one object with all the items pointed to or listed in some way. And that it should be possible to copy the entire object as one thing to an inventory on one of the pcs. But that would need a code function. It is unlikely that it was thought necessary to move an entire inventory so that would probably need new code.

 

In TDM there are none of the great variety of links available to Dromeders. For instance, the nearest feature to a control device link is probably the target property. This is limited and universal. Add a target property to say, a lever, with a door as its value and the lever can open the door. A contains link equivalent might be bind in the case of adding a key or purse to a guard's belt - or there is an attach property too (but inventories are not the same as this.) Chests do not need links because the stuff is literally inside. Nor are TDM conversations as flexible as Thief - they are mainly focused on actual conversations and actions related thereto so they cannot change links as Thief does. So there is no direct access to the inventory except by script or code. Fortunately we do have access to the code for those knowledgeable enough so the sky is the limit! But currently there are far more important code issues for coders to deal with than this. If ever this was pursused then I think a new entity eg, atdm:target_swap_inventories might be simplest for the mapper.

Link to post
Share on other sites

Yes, but coop is a galaxy more complicated than just switching characters. Almost everything that can happen in the game is configured for one player ... frob-highlighting, frobbing, inventory, loot, script events, location settings, sound, triggers, the objectives. You'd have to completely rewrite all of those systems to handle another player milling around the world at the same time so that the game can distinguish what happens for one player vs the other vs both. Whereas if you just "switch" characters with the same player, you can keep all of that and you just need to tweak the inventory code a little, teleport the player, and maybe leave a thief avatar in its place. It's much lower hanging fruit. That said, I think coop would be very cool too if someone ever got around to doing all that work.

What do you see when you turn out the light? I can't tell you but I know that it's mine.

Link to post
Share on other sites

Although we in Dark Mod would have to use slightly different methods, the principles are the same so that's a good reference Haplo, thanks.

 

After being reminded yesterday about Head Over Heels I did a quick test in Dark Mod. It is possible to bind player clip to the other pcs so you can stand on their shoulders. That would add a little more gameplay to get onto high ledges, over walls etc where there is no wood to rope to. I don't know if that is possible in Dromed though.

Link to post
Share on other sites
After being reminded yesterday about Head Over Heels I did a quick test in Dark Mod. It is possible to bind player clip to the other npcs so you can stand on their shoulders. That would add a little more gameplay to get onto high ledges, over walls etc where there is no wood to rope to.

Hey, cool! :)

-> Crisis of Capitalism

-> 9/11 Truth

->

(hard stuff), more
Link to post
Share on other sites
  • 2 weeks later...

After being reminded yesterday about Head Over Heels I did a quick test in Dark Mod. It is possible to bind player clip to the other pcs so you can stand on their shoulders. That would add a little more gameplay to get onto high ledges, over walls etc where there is no wood to rope to. I don't know if that is possible in Dromed though.

You could also look at how the horse is set up, physically. I'm not sure if that's exactly what you're looking for, but you can climb and mantle on that without the need for extra bound player clip entities.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...