Frictional Games Forum (read-only)
Several advanced(probably) questions - Printable Version

+- Frictional Games Forum (read-only) (https://www.frictionalgames.com/forum)
+-- Forum: Amnesia: The Dark Descent (https://www.frictionalgames.com/forum/forum-6.html)
+--- Forum: Custom Stories, TCs & Mods - Development (https://www.frictionalgames.com/forum/forum-38.html)
+---- Forum: Development Support (https://www.frictionalgames.com/forum/forum-39.html)
+---- Thread: Several advanced(probably) questions (/thread-56415.html)



Several advanced(probably) questions - MistaEinstein - 06-18-2019

Good day, gentlemen!



Currently i am developing a new project and i have some serious troubles with realization of several ideas i'd thought are very cool. I am sorry for such a long and boring text, but i'd like to ask all the questions i had during my period of developing.
  • 1) So, i'd like to start from the stupidest question. Is this possible to somehow upgrade an editor and add new functions to it?
Well, i don't need this exactly - i just want to say that it is kinda irritating when it comes to making realistic lights. If you have, for example, a lamp, to make shadows you should literally spam spotlights around it imitating effect of shadows coming from the lamp.


[Image: image.jpg]


[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]

Sometimes, shadows from different lights cross and it looks terrible as hell:

[Image: 2.jpg]
 

[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]


Is there a possibility to make something similar to pointlight, but with casting shadows?


  • 2) Besides of that, there is something wrong with ropes. First of all, it doesn't really have collision or something - it always goes through walls and objects. Ofcourse, i'd like to fix this, but that's not a big problem.
There is a thing that i wanted to make recently. I connected an object to table using rope, so my idea was to move this object in some exact radius around the table, and push the table in another places to extend the radius.

Things went backward. When i take an object and go somewhere, the table itself goes right after me. It could be realistic, but not in my case, because the thing i bring with me has a very small mass(something around 1 vs 20 of table). I even tried to launch it somewhere - and table just went flying over there like a piece of paper.
I tried changing mass of both but it didn't help. It works only if the table is static object, but this already ruins the whole idea.

  • 3) Monster paths.
I have a location that has two floors. Monster follows me incredibly good until we stop being on the same height. When it reaches stairs - oh my God - it will never pass it without making some stupid move like breakdancing around itself. And it is if i am lucky enough. Sometimes it just skips stairs and tries to reach me, going in the same position i am, but a floor lower. And, again, breakdancing.

What should i do to fix it? Will monster work relatively correct in a location with several floors?

  • 4) Monster again.
I wanted to give him some kind of moves like ability to open doors instead of just breaking them. How can i make him to open doors when he is not chasing me?

The reason i want it to do is because there will always be a moment on the map when all doors are broken.

  • 5) Troubles with phonograph.
For some reason, it stucks after activating exact script. It might be kind of a noob mistake, but i really don't understand why it does such a thing with all the settings i made:


[Image: 221.jpg]


Code:
void Phonograph(string &in asEntityName, int alState)
{
if(alState == 1)
{
PlayMusic("Mus1.ogg", false, 1, 3, 3, false);
}

if(alState == 0)
{
StopMusic(1, 3);
}
}

  • 6) Problems with primitives and areas
I needed to make a slow increasing of water in some room. But i can't work with primitives like with entities, thus, i can't give it a script. How can i handle this situation?

The problem connected to it is i don't know if areas can be attached to objects. I tried it but it wouldn't work. As you already figured out, i wanted to make an increasing level of water with expanding the water area so all objects can be affected by water physics.

And i still don't know what to do in case if it reaches head of the player. Should i just end a game or somehow make him going up as well?






Well, i surely forgot some of the things i wanted to ask, but, whatever, these are the most important things needed for my map.


Thanks for reading or at least scrolling until this part! I hope i didn't act impertinently enough with asking all these questions at once.


RE: Several advanced(probably) questions - Romulator - 06-19-2019

Wew, a lot of things at once.

1. Short answer; no. We don't have the source code.

Long answer: No - and frankly, don't use too many spotlights. Just use a Pointlight or a few. You don't need to have shadows everywhere, and given how bright that lamp is (it's too bright, it's white light, mind you), even if a shadow were cast, light bouncing off walls would really lower the amount of shadow.

2. Ropes will try to always go 'as the crow flies' from point A to point B; through walls and objects if they must. They will elasticise and rest (think of it like how gravity arches a piece of string downward if there is slack) but will still go through the floor, off the top of my head. Your issue with the objects may be more linked to the strength of the rope. I don't have much experience with ropes but it wouldn't surprise me if what you are trying to do is a bit difficult with ropes alone, but you may have more luck with an edited model, since I bet you can get a similar effect with how the pig corpse and an interactable ragdoll work.

3. Put a PathNode on each step.

4. Create a ScriptArea around the door, and add a collide callback where the enemy or enemies are parents and the ScriptArea is the child. Check for what state the monster is in, and open the door using force when they enter the area, and close it when they exit.

Spoiler below!

PHP Code:
void OnEnter()
{
    
AddEntityCollideCallback("servant_grunt_1""ScriptDoorOpen_1""InteractWithDoor"false0);
}

void InteractWithDoor(string &in asParentstring &in asChildint alState)
{
    
//You need to edit this code, supply the name of the door to open 
    //as it is named in your map. You can also use "|| (GetEnemyStateName(asParent)"
    //to check for more than just the Patrol state. See the Engine Scripts page.
    
    
string door "<name of door>";
    if(
alState == 1)
    {

        if(
GetEnemyStateName(asParent) == "Patrol")
        {
            
//Enemy has entered area and is just patrolling (normal walking state).
            //First set the door to not close automatically so it can be opened via script.
            
SetSwingDoorDisableAutoClose(doortrue);
            
//Now open the door. You may want to use either AddPropForce or AddPropImpulse. 
            //Open against Positive/Negative X/Z axis depending on which way the door faces.
        
}
    }
    else
    {
        
//Enemy leaves area. Just close the door.
        
SetSwingDoorDisableAutoClose(doorfalse);
        
SetSwingDoorClosed(doortruetrue);
    }


Please see Conditionals and the Engine Scripts page for more information about the code segment above.

If you are using a retail copy of Amnesia (i.e., you purchased it from Frictional Games directly or bought it in stores forever ago), you need to be on Update 1.3 or above to use GetEnemyStateName. If you need to update, you can do so from here.

5. Personally, I'd keep track of a variable which functions like a boolean, and just switch between the two.

Spoiler below!

PHP Code:
void Phonograph(string &in asEntityNameint alState)
{
    if(
alState == 1)
    {
        if(
GetLocalVarInt("PhonographPlaying") == 1)
        {
            
StopMusic(13);
            
SetLocalVarInt("PhonographPlaying"0);
        }
    }
    else
    {
        
PlayMusic("Mus1.ogg"false133false);
        
SetLocalVarInt("PhonographPlaying"1);
    }
    
SetWheelInteractionDisablesStuck("Phonograph"true);
    
SetWheelAngle("Phonograph", -180false);



6. Now I think you can move Areas with SetEntityPos(). As such, you should be able to move Liquid Areas using a looping timer. Place down the water plane entity in entities/special/water_planes/ and use SetEntityPos to raise the entity, and do the same with the LiquidArea. Repeat until greater than the desired height. Have the LiquidArea scaled in such a way that its topmost bit is in line with the entity for the best effect.

Spoiler below!

PHP Code:
void RiseWater(string &in asTimer)
{
    
//Increase or decrease these to change the speed or rise of the water.
    
float TimerTick 0.25f //Tick every 1/4th of a second
    
float increaseY 0.125f //Rise by 0.125f on the Y axis.
    
    //Do until greater than the desired height. In this case, 3.5 Y.
    
if(GetEntityPosY("water_plane_ch02_16") > 3.5f)
    {
        
SetEntityPos("LiquidArea_1"GetEntityPosX("LiquidArea_1"), GetEntityPosY("LiquidArea_1")+increaseYGetEntityPosZ("LiquidArea_1");
        
SetEntityPos("water_plane_ch02_16"GetEntityPosX("water_plane_ch02_16"), GetEntityPosY("water_plane_ch02_16")+increaseYGetEntityPosZ("water_plane_ch02_16");
    }
    else 
AddTimer("newRiseWaterTimer"TimerTick"RiseWater");





RE: Several advanced(probably) questions - MistaEinstein - 06-19-2019

(06-19-2019, 12:49 PM)Romulator Wrote: Wew, a lot of things at once.

1. Short answer; no. We don't have the source code.

Long answer: No - and frankly, don't use too many spotlights. Just use a Pointlight or a few. You don't need to have shadows everywhere, and given how bright that lamp is (it's too bright, it's white light, mind you), even if a shadow were cast, light bouncing off walls would really lower the amount of shadow.

2. Ropes will try to always go 'as the crow flies' from point A to point B; through walls and objects if they must. They will elasticise and rest (think of it like how gravity arches a piece of string downward if there is slack) but will still go through the floor, off the top of my head. Your issue with the objects may be more linked to the strength of the rope. I don't have much experience with ropes but it wouldn't surprise me if what you are trying to do is a bit difficult with ropes alone, but you may have more luck with an edited model, since I bet you can get a similar effect with how the pig corpse and an interactable ragdoll work.

3. Put a PathNode on each step.

4. Create a ScriptArea around the door, and add a collide callback where the enemy or enemies are parents and the ScriptArea is the child. Check for what state the monster is in, and open the door using force when they enter the area, and close it when they exit.

Spoiler below!

PHP Code:
void OnEnter()
{
    
AddEntityCollideCallback("servant_grunt_1""ScriptDoorOpen_1""InteractWithDoor"false0);
}

void InteractWithDoor(string &in asParentstring &in asChildint alState)
{
    
//You need to edit this code, supply the name of the door to open 
    //as it is named in your map. You can also use "|| (GetEnemyStateName(asParent)"
    //to check for more than just the Patrol state. See the Engine Scripts page.
    
    
string door "<name of door>";
    if(
alState == 1)
    {

        if(
GetEnemyStateName(asParent) == "Patrol")
        {
            
//Enemy has entered area and is just patrolling (normal walking state).
            //First set the door to not close automatically so it can be opened via script.
            
SetSwingDoorDisableAutoClose(doortrue);
            
//Now open the door. You may want to use either AddPropForce or AddPropImpulse. 
            //Open against Positive/Negative X/Z axis depending on which way the door faces.
        
}
    }
    else
    {
        
//Enemy leaves area. Just close the door.
        
SetSwingDoorDisableAutoClose(doorfalse);
        
SetSwingDoorClosed(doortruetrue);
    }


Please see Conditionals and the Engine Scripts page for more information about the code segment above.

If you are using a retail copy of Amnesia (i.e., you purchased it from Frictional Games directly or bought it in stores forever ago), you need to be on Update 1.3 or above to use GetEnemyStateName. If you need to update, you can do so from here.

5. Personally, I'd keep track of a variable which functions like a boolean, and just switch between the two.

Spoiler below!

PHP Code:
void Phonograph(string &in asEntityNameint alState)
{
    if(
alState == 1)
    {
        if(
GetLocalVarInt("PhonographPlaying") == 1)
        {
            
StopMusic(13);
            
SetLocalVarInt("PhonographPlaying"0);
        }
    }
    else
    {
        
PlayMusic("Mus1.ogg"false133false);
        
SetLocalVarInt("PhonographPlaying"1);
    }
    
SetWheelInteractionDisablesStuck("Phonograph"true);
    
SetWheelAngle("Phonograph", -180false);



6. Now I think you can move Areas with SetEntityPos(). As such, you should be able to move Liquid Areas using a looping timer. Place down the water plane entity in entities/special/water_planes/ and use SetEntityPos to raise the entity, and do the same with the LiquidArea. Repeat until greater than the desired height. Have the LiquidArea scaled in such a way that its topmost bit is in line with the entity for the best effect.

Spoiler below!

PHP Code:
void RiseWater(string &in asTimer)
{
    
//Increase or decrease these to change the speed or rise of the water.
    
float TimerTick 0.25f //Tick every 1/4th of a second
    
float increaseY 0.125f //Rise by 0.125f on the Y axis.
    
    //Do until greater than the desired height. In this case, 3.5 Y.
    
if(GetEntityPosY("water_plane_ch02_16") > 3.5f)
    {
        
SetEntityPos("LiquidArea_1"GetEntityPosX("LiquidArea_1"), GetEntityPosY("LiquidArea_1")+increaseYGetEntityPosZ("LiquidArea_1");
        
SetEntityPos("water_plane_ch02_16"GetEntityPosX("water_plane_ch02_16"), GetEntityPosY("water_plane_ch02_16")+increaseYGetEntityPosZ("water_plane_ch02_16");
    }
    else 
AddTimer("newRiseWaterTimer"TimerTick"RiseWater");



God bless you, sir. Thanks for the help.


RE: Several advanced(probably) questions - Mudbill - 06-20-2019

I want to add for #3 that it might help to make a custom entity and use the ManPig enemy type (if you have version 1.3 of Amnesia). I've heard this AI seems to be more "intelligent". What exactly this means I haven't tested, but might be worth a try.

As for #5, I think the phonograph automatically becomes stuck by default when you turn it. Maybe try ResetProp("Phonograph");

Lastly, for #6, I have tested moving LiquidAreas before, and if I remember correctly, if you move a LiquidArea away from the player after entering it, the game won't detect the player leaving it, so they'll be splashing around until you re-enter the area and then leave manually. Maybe this is the case with other entities. I can expect moving LiquidAreas with script to be buggy, so worth testing.
If you need the actual water primitive to move, perhaps make an entity out of a basic plane model using the water texture, then set the entity type to MoveObject and have it move along the Y axis.
It is also possible (although difficult) to simulate some swimming mechanics using script. I know there are a few examples here and there on the forums or elsewhere.


RE: Several advanced(probably) questions - MistaEinstein - 06-21-2019

(06-20-2019, 06:08 PM)Mudbill Wrote: I want to add for #3 that it might help to make a custom entity and use the ManPig enemy type (if you have version 1.3 of Amnesia). I've heard this AI seems to be more "intelligent". What exactly this means I haven't tested, but might be worth a try.

As for #5, I think the phonograph automatically becomes stuck by default when you turn it. Maybe try ResetProp("Phonograph");

Lastly, for #6, I have tested moving LiquidAreas before, and if I remember correctly, if you move a LiquidArea away from the player after entering it, the game won't detect the player leaving it, so they'll be splashing around until you re-enter the area and then leave manually. Maybe this is the case with other entities. I can expect moving LiquidAreas with script to be buggy, so worth testing.
If you need the actual water primitive to move, perhaps make an entity out of a basic plane model using the water texture, then set the entity type to MoveObject and have it move along the Y axis.
It is also possible (although difficult) to simulate some swimming mechanics using script. I know there are a few examples here and there on the forums or elsewhere.


About #3: I also didnt test ManPig enemy type but i placed them several times just for fun. It seems they require harder scripting because they didnt move an inch by themselves.

About #5: Oh, well, it is actually much more easy than i thought. I didn't even need to add any variables - all i did was changing some phonograph's preferences like direction of spinning wheel, e.t.c. I don't quite understand "OverrideDefaults" function though, but it somehow helped me.



Here's the code:
Code:
void Phonograph(string &in asEntityName, int alState)
{
   if(alState == 1)
   {
     
          PlaySoundAtEntity("Phono", "Mus1.snt", "phonograph", 1, false);
   
   }
  if(alState == -1)
   {
    StopSound("Phono", 0);
    
       
   }

And, also, about #6: Yeah, it is such a pain in the back. I was thinking about making a block-box that moves along with liquid area in case of liquid area bugging, but then player will also start behave strangely.

Also i somehow need to block the path to the water when it is too high, and kill player in case of him being in the area at this exact moment, but it doesn't seem to be a big problem. The thing i am worried about is critter entities and enemies. And if i can relatively control movements of enemy, spider or cockroach is not something i can control, though it'd be amazing to see a spider on the celling in the room filled with water.



P.S: Oh, also, its a nice opportunity to ask a question. Have you ever had bugs with attached lights and billboards to entities? Recently i faced one problem: i added the effect of red eyes to the monster, but when he fades to smoke or is not active, lights and billboards remain on the place.


RE: Several advanced(probably) questions - Mudbill - 06-21-2019

Can't say I've experienced that but I have also never tried it. I can see why it bugs, because billboards are a bit tricky to enable/disable like that.

It might help to maybe set the entity inactive after it has faded away if you can detect that. But first do try to see if a disabled enemy still displays the billboards.


RE: Several advanced(probably) questions - Romulator - 06-21-2019

If I can offer some support, we do have a Discord server where a couple of other modders could help out as well if you're interested. You could ask for some assistance with scripting and we may be able to provide more support and perhaps in real-time too, depending on who is online.

A link, if you are interested: https://discordapp.com/invite/dKNcz4A

Also, you mentioned being a bit unsure as to what "Override Defaults" accomplishes -- that basically refers to whether or not the entity should prioritise settings you have made in the Level Editor as opposed to the settings specified in the User Defined Variables in the Model Editor.


RE: Several advanced(probably) questions - MistaEinstein - 06-21-2019

(06-21-2019, 02:15 AM)Mudbill Wrote: Can't say I've experienced that but I have also never tried it. I can see why it bugs, because billboards are a bit tricky to enable/disable like that.

It might help to maybe set the entity inactive after it has faded away if you can detect that. But first do try to see if a disabled enemy still displays the billboards.

Yes, when entity is inactive it still displays lights and billboards. Even more of it - it displays it right from the start of the map, without any scripts or something.


RE: Several advanced(probably) questions - MistaEinstein - 06-21-2019

(06-21-2019, 08:21 AM)Romulator Wrote: If I can offer some support, we do have a Discord server where a couple of other modders could help out as well if you're interested. You could ask for some assistance with scripting and we may be able to provide more support and perhaps in real-time too, depending on who is online.

A link, if you are interested: https://discordapp.com/invite/dKNcz4A

Also, you mentioned being a bit unsure as to what "Override Defaults" accomplishes -- that basically refers to whether or not the entity should prioritise settings you have made in the Level Editor as opposed to the settings specified in the User Defined Variables in the Model Editor.

Sure, i'll join it right now.