Jump to content
The Dark Mod Forums

Things that could be improved


Berny

Recommended Posts

Default def files are in the game's pk4s. Changing those changes all maps that just use the defaults.

So if I place the changed def file outside the pk4, will it override the included version or do I need to pack it into the pk4 instead?

 

Changing the author's intent is not what I want and I believe a lot of you are overreacting to the suggestion. When I tried to test my changes I loaded the last missions that I played and it was hard to find an oil lamp in reach in the first place! This is not about making missions easier, but making the game world more consistent...

Edited by wesp5
Link to comment
Share on other sites

The default def file is already somewhere in a pk4 in the parent folder (inside /darkmod, or whatever you call it). So changing it changes it. I forget the rule of priority when you duplicate them, except that an FM's pk4 always has priority over the default. But anyway, you don't have to make a duplicate and put it outside the pk4. Just change the default already in there somewhere and you've changed it. A pk4 is just a zip file, don't forget.

 

I actually don't care why you'd want to change things. I'd only observe some changes are good to be imposed on everybody, and some are better as 'house rules' for your local game. I think very creative or 'ultra-realist' types of changes are in the 2nd category, and people should feel like it's natural to just change things locally to suit their taste. And maybe then let people know things you liked to guage if others think so too.

 

Anyway, that's my tendency. I change stuff locally all the time, and even FMs from time to time (don't tell their authors!) I don't try to presume anyone else has to like it. I just do it, or ask for directions. But I've also followed a lot of the gameplay debates that make me appreciate how much thought has gone into most features the way they are, or the limits of some ideas. Sometimes I try to sell what I think is a good idea too though.

  • Like 1

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

Link to comment
Share on other sites

Anyway, that's my tendency. I change stuff locally all the time, and even FMs from time to time (don't tell their authors!) I don't try to presume anyone else has to like it. I just do it, or ask for directions. But I've also followed a lot of the gameplay debates that make me appreciate how much thought has gone into most features the way they are, or the limits of some ideas. Sometimes I try to sell what I think is a good idea too though.

I wasn't aware that changing things in TDM could be so easy for people like you. I'm aware that some people modify my Bloodlines patch for their special needs as well, but most of the time when people argue to include stuff that makes sense to me I do. Or I add an option to turn it on and off if I see that there are two parties with different opinions. Maybe this would be possible here too...

Link to comment
Share on other sites

I completely agree with demagogue. If it is possible (and you are able) to change things you don't like or like better than offered, try to change it. You don't have to impose everything on others, just as they don't have to impose their changes on you.

 

To the problem at hand: I think I am circling in on the problem: I tried to set up a stim/response pair in DR itself and wanted to copy the results into the def-file. This looked quite promising at first, but I cannot get the flame to be extinguished by the s/r pair. I can set it up to kill an AI, I can set it up to teleport itself, but the "turn extinguishable light off" does not work. I don't know if this generally does not work, but at least for the atdm:lamp_oil_standing_rusty_lit it simply is not possible to extinguish the flame via a response. If this can somehow be circumvented, the whole thing should work. But right now, I am kind of desperate :(

 

Right now the script I inserted looks as follows:

 

"frobable" "1"
"sr_class_1" "S"
"sr_type_1" "STIM_FROB"
"sr_state_1" "1"
"sr_class_2" "R"
"sr_type_2" "STIM_FROB"
"sr_state_2" "1"
"sr_effect_2_1" "effect_light_extinguish"
"sr_effect_2_1" "_SELF"

Edited by Destined
Link to comment
Share on other sites

I suspect that's http://bugs.thedarkmod.com/view.php?id=4195

 

SteveL provided a copy of the updated tdm_response_effects.script from SVN:

 

 

 

/***********************************************************************
tdm_response_effects.script

These are the functions that are referenced in tdm_response_effects.def
All the "atomic" effects are executed here.
***********************************************************************/

#ifndef __DARKMOD_RESPONSE_EFFECTS__
#define __DARKMOD_RESPONSE_EFFECTS__

#include "script/tdm_ai.script"
#include "script/tdm_lights.script"
#include "script/tdm_ai_base.script"
#include "script/tdm_light_holders.script"  // #4195


namespace StimResponse {

#define STR_ENTITY_SELF "_SELF"
#define ECLASS_EMITTER "func_emitter"

/**
*    This is where the reponse effects are performed.
*
*    This is    a prototype of such a function, it has to take
*    two entities, a string and two floats (threadnum and magnitude) as argument.
*
*    void sr_effect_BLA_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
*        // your action code here
*   }
*/

/**
* Returns either the entity as specified by <targetEntityStr>
* or the <self> entity, if the STR_ENTITY_SELF is found.
* Note that <self> is referring to the "response entity", which can be
* a different one (imagine AI heads and AI body, the heads will return
* the body as "response entity".
*/
entity getTargetEntity(string targetEntityStr, entity self) {
    // Check, if the "owner" should be returned
    if (targetEntityStr == STR_ENTITY_SELF) {
        return self.GetResponseEntity();
    }
    else {
        return sys.getEntity(targetEntityStr);
    }
}

float isActive(entity owner, string effectPostfix) {
    if (owner.getKey("sr_effect_" + effectPostfix + "_state") == "0") {
        return 0;
    }
    else {
        // Always default to "1" even if the key is not set at all
        return 1;
    }
}

void effect_damage_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;
    
    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the damage value as first argument
    entity damageTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    string damageType = owner.getKey(argRoot + "2");

    // Deal the damage (the magnitude is passed as scaling factor)
    damageTarget.damage(stimEnt, stimEnt, stimEnt.getOrigin(), damageType, magnitude);
}

void effect_heal_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;
    
    if (magnitude <= 0) {
        return;
    }

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the damage value as first argument
    entity healTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Heal the entity using the second argument as healDefName
    float healed = owner.heal(owner.getKey(argRoot + "2"), magnitude);

    // If the entity could be healed (returnvalue != 0), play the sound, if there is one
    if (healed != 0) {
        // Do we have a non-empty soundshader string specified
        string soundShader = owner.getKey(argRoot + "3");
        if (soundShader != "") {
            sys.cacheSoundShader(soundShader);

            // If the soundchannel argument is empty
            owner.startSoundShader(soundShader, SND_CHANNEL_VOICE);
        }
    }
}

void effect_kill_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    entity damageTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Deal the damage
    damageTarget.damage(stimEnt, stimEnt, stimEnt.getOrigin(), "damage_suicide", 1.0);
}

void effect_knockout_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {

    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Check if we have a projectile owner here
    string projectileOwner = stimEnt.getKey("projectile_owner");
    entity originator = $null_entity;
    if (projectileOwner != "") {
        originator = sys.getEntity(projectileOwner);
    }

    entity koTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Try to knockout the entity

    koTarget.KO_Knockout(originator);
}

// grayman #2468 - gas knockout effect

void effect_gas_knockout_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {

    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Check if we have a projectile owner here
    string projectileOwner = stimEnt.getKey("projectile_owner");
    entity originator = $null_entity;
    if (projectileOwner != "") {
        originator = sys.getEntity(projectileOwner);
    }

    entity koTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Try to knockout the entity

    koTarget.Gas_Knockout(originator);
}

void effect_remove_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    entity removeEnt = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Remove the target entity
    removeEnt.remove();
}

void effect_trigger_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    entity triggerTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Check for an activator string (optional argument)
    string activatorStr = owner.getKey(argRoot + "2");

    // The activator entity is set to the player entity, if the key is empty
    entity activatorEntity = $player1;
    if (activatorStr != "") {
        activatorEntity = getTargetEntity(activatorStr, owner);
    }

    // Trigger the target entity
    triggerTarget.activate(activatorEntity);
}

void effect_play_sound_shader_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    string soundShader = owner.getKey(argRoot + "1");
    sys.cacheSoundShader(soundShader);

    // If the soundchannel argument is empty, the float defaults to 0, which is SND_CHANNEL_ANY
    owner.startSoundShader(soundShader, owner.getFloatKey(argRoot + "2"));
}

// Plays the SOUND (as defined in a "snd_" spawnarg), not to be confused with play SOUND SHADER
void effect_play_sound_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    string soundName = owner.getKey(argRoot + "1");

    // If the soundchannel argument is empty, the float defaults to 0, which is SND_CHANNEL_ANY
    owner.startSound(soundName, owner.getFloatKey(argRoot + "2"), false);
}

void effect_set_model_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity modelTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    // Set the model on the entity as specified in the second argument
    modelTarget.setModel(owner.getKey(argRoot + "2"));
}

void effect_set_skin_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity skinTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    // Set the skin on the entity as specified in the second argument
    skinTarget.setSkin(owner.getKey(argRoot + "2"));
}

void effect_set_spawnarg_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity spTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    // Set the spawnarg key to the value (argument 2 = key, argument 3 = value)
    spTarget.setKey(owner.getKey(argRoot + "2"), owner.getKey(argRoot + "3"));
}

void effect_toggle_light_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Retrive the light target entity
    entity lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    if (lightTarget.getLightLevel() > 0) {
        lightTarget.Off();
        // Check for a "extinguished" model
        string extModel = lightTarget.getKey("model_extinguished");
        if (extModel != "") {
            lightTarget.setModel(extModel);
        }
    }
    else {
        lightTarget.On();
        // Check for a "lit" model
        string litModel = lightTarget.getKey("model_lit");
        if (litModel != "") {
            lightTarget.setModel(litModel);
        }
    }
}

void effect_light_ignite_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Retrieve the light target entity
    entity lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    light_moving_ext thelight = lightTarget;
    thelight.response_ignite(stimEnt, 0);
}

void effect_light_extinguish_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Retrieve the light target entity
    entity lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    light_moving_ext thelight = lightTarget;
    thelight.response_extinguish(stimEnt, 0);
}

void effect_light_on_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Use the script object, don't try to operate the light directly -- SteveL #4195
    tdm_light_holder lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    lightTarget.LightsOn();
    
    // Check for a "lit" model
    string litModel = lightTarget.getKey("model_lit");
    if (litModel != "") {
        lightTarget.setModel(litModel);
    }
}

void effect_light_off_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Use the script object, don't try to operate the light directly -- SteveL #4195
    tdm_light_holder lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    // lightTarget.setRadius(0); // SteveL #4186
    lightTarget.LightsOff();
    
    // Check for a "extinguished" model
    string extModel = lightTarget.getKey("model_extinguished");
    if (extModel != "") {
        lightTarget.setModel(extModel);
    }
}

void effect_set_light_color_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    entity lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    vector color = owner.getVectorKey(argRoot + "2");
    lightTarget.setLightParms( color_x, color_y, color_z, 1 );
}

void effect_fade_light_color_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    entity lightTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    vector targetColor = owner.getVectorKey(argRoot + "2");
    float fadeTime = owner.getFloatKey(argRoot + "3");

    vector currentColor;
    currentColor_x = lightTarget.getLightParm(0);
    currentColor_y = lightTarget.getLightParm(1);
    currentColor_z = lightTarget.getLightParm(2);

    vector diffColor = targetColor - currentColor;
    float numIterations = 20;

    float i;
    for (i = 0; i < numIterations; i++) {
        currentColor_x += diffColor_x / numIterations;
        currentColor_y += diffColor_y / numIterations;
        currentColor_z += diffColor_z / numIterations;
        lightTarget.setLightParms( currentColor_x, currentColor_y, currentColor_z, 1 );
        sys.wait(fadeTime/numIterations);
    }

    lightTarget.setLightParms( targetColor_x, targetColor_y, targetColor_z, 1 );
}

void effect_play_animation_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity animTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);
    
    float channel = owner.getFloatKey(argRoot + "3");

    // Default to ANIMCHANNEL_TORSO, if the spawnarg is empty
    if (owner.getKey(argRoot + "3") == "") {
        channel = ANIMCHANNEL_TORSO;
    }

    // Try to play the animation (argument 2 = anim string, argument 3 = channel (defaults to ANIMCHANNEL_TORSO))
    animTarget.playAnim(channel, owner.getKey(argRoot + "2"));
    
    while (!animTarget.animDone(channel, 0)) {
        sys.waitFrame();
    }

    // Play the idle animation when done
    animTarget.playAnim(channel, "idle");
}

void effect_set_ai_team_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity target = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    float team = owner.getFloatKey(argRoot + "2");
    target.setTeam(team);
}

void effect_apply_stim_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity responseTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the stim type (default would be 0)
    float stimType = owner.getFloatKey(argRoot + "2");

    // Get the source entity (defaults to owner if empty)
    entity stimSource = getTargetEntity(owner.getKey(argRoot + "3"), owner);
    if (owner.getKey(argRoot + "3") == "") {
        stimSource = owner;
    }

    // Trigger the response
    responseTarget.ResponseTrigger(stimSource, stimType);
}

void effect_teleport_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity teleportTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the vector
    vector v = owner.getVectorKey(argRoot + "2");

    // Is this relative positioning?
    if (owner.getKey(argRoot + "3") == "1") {
        // Add the current origin
        v += teleportTarget.getOrigin();
    }

    // Move the origin
    teleportTarget.setOrigin(v);
}

void effect_move_to_position_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity moveTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the vector
    vector v = owner.getVectorKey(argRoot + "2");

    // Is this relative positioning?
    if (owner.getKey(argRoot + "3") == "1") {
        // Add the current origin
        v += moveTarget.getOrigin();
    }

    // Tell the entity to move
    moveTarget.moveToPosition(v);

    while (1) {
        sys.waitFrame();
        // Have we reached the target?
        if (moveTarget.moveStatus() == MOVE_STATUS_DONE) {
            // Notify the entity
            moveTarget.ResponseTrigger(moveTarget, STIM_TARGET_REACHED);
            break;
        }
    }
}

void effect_move_to_random_position_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity moveTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the vector
    float radius = owner.getFloatKey(argRoot + "2");

    float counter = 0;
    while (moveTarget.moveStatus() != MOVE_STATUS_MOVING && counter < 5000) {
        vector v;
        // Create a new position candidate, if this one is unreachable
        v_x = sys.random(radius) - radius/2;
        v_y = sys.random(radius) - radius/2;
        v_z = 0;
        v += moveTarget.getOrigin();
        counter++;

        // Tell the entity to move to that position
        moveTarget.moveToPosition(v);

        sys.waitFrame();
    }

    while (1) {
        sys.waitFrame();
        // Have we reached the target?
        if (moveTarget.moveStatus() == MOVE_STATUS_DONE) {
            // Notify the entity
            moveTarget.ResponseTrigger(moveTarget, STIM_TARGET_REACHED);
            break;
        }
    }
}

void effect_set_angles_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity angleTarget = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the vector
    vector angles = owner.getVectorKey(argRoot + "2");

    // Is this measured relatively to the current angles?
    if (owner.getKey(argRoot + "3") == "1") {
        // Add the current origin
        angles += angleTarget.getAngles();
    }

    // Trigger the response
    angleTarget.setAngles(angles);
}

void effect_spawn_entity_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity newEntity = sys.spawn(owner.getKey(argRoot + "1"));

    // Place the new entity at the specified location
    newEntity.setOrigin(owner.getVectorKey(argRoot + "2"));

    // Show the entity, to make sure
    newEntity.show();
}

void effect_disable_effect_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    string targetEffectPostfix = owner.getKey(argRoot + "2");
    targetEntity.setKey("sr_effect_" + targetEffectPostfix + "_state", "0");
}

void effect_enable_effect_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    string targetEffectPostfix = owner.getKey(argRoot + "2");
    targetEntity.setKey("sr_effect_" + targetEffectPostfix + "_state", "1");
}

void effect_toggle_effect_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    string targetEffectPostfix = owner.getKey(argRoot + "2");

    // Invert the current state
    string curState = targetEntity.getKey("sr_effect_" + targetEffectPostfix + "_state");
    string newState;
    if (curState == "0") {
        newState = "1";
    }
    else {
        newState = "0";
    }

    // Set the inverted state on the target entity
    sys.print("Setting effect state on " + targetEntity.getKey("name") + " to " + newState + " (effectPostfix: " + targetEffectPostfix + ")\n");
    targetEntity.setKey("sr_effect_" + targetEffectPostfix + "_state", newState);
}

void effect_activate_stim_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Set the stim state on the target entity
    targetEntity.StimEnable(stimTypeID, 1);
}

void effect_deactivate_stim_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Set the stim state on the target entity
    targetEntity.StimEnable(stimTypeID, 0);
}

void effect_activate_response_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Set the response state on the target entity
    targetEntity.ResponseEnable(stimTypeID, 1);
}

void effect_deactivate_response_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Set the response state on the target entity
    targetEntity.ResponseEnable(stimTypeID, 0);
}

void effect_start_stim_timer_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Start the timer on the target entity
    targetEntity.StartTimer(stimTypeID);
}

void effect_stop_stim_timer_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Set the "effect_x_y_state" spawnarg to 0 to disable the effect
    float stimTypeID = owner.getFloatKey(argRoot + "2");

    // Stop the timer on the target entity
    targetEntity.StopTimer(stimTypeID);
}

void effect_spawn_particle_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity newEntity = sys.spawn(ECLASS_EMITTER);
    
    // Place the new entity at the specified location
    newEntity.setOrigin(owner.getVectorKey(argRoot + "1"));
    newEntity.setModel(owner.getKey(argRoot + "2"));
    newEntity.setShaderParm(SHADERPARM_PARTICLE_STOPTIME, 0);
    newEntity.setShaderParm(SHADERPARM_TIMEOFFSET, -sys.getTime());

    // Show the entity, to make sure
    newEntity.show();

    float lifetime = owner.getFloatKey(argRoot + "3");
    if (lifetime > 0) {
        sys.wait(lifetime);
        newEntity.remove();
    }
}

void effect_blind_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Try to blind the target AI entity (use second argument as "skipVisibility" bool)
    targetEntity.processBlindStim(stimEnt, owner.getFloatKey(argRoot + "2"));
}

void effect_activate_shooter_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Try to activate the shooter
    targetEntity.shooterSetState(1);
}

void effect_deactivate_shooter_action(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Try to deactivate the shooter
    targetEntity.shooterSetState(0);
}

void effect_frob(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Frob the entity
    targetEntity.frob();
}

void effect_set_frobable(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // Get the bool
    boolean frobable = owner.getIntKey(argRoot + "2");

    // Try to set the frobable status
    targetEntity.setFrobable(frobable);
}

void effect_clear_targets(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    float num = targetEntity.numTargets();
    float i;
    for( i = 0; i < num; i++ )
    {
        targetEntity.removeTarget( targetEntity.getTarget(i) );
    }
}

void effect_add_target(entity owner, entity stimEnt, string effectPostfix, float magnitude, float threadNum) {
    if (!isActive(owner, effectPostfix)) return;

    // Search for something like "sr_effect_1_1_argN"
    string argRoot = "sr_effect_" + effectPostfix + "_arg";

    // Get the target entity
    entity targetEntity = getTargetEntity(owner.getKey(argRoot + "1"), owner);

    // get the argument entity (the one we want to set to target)
    entity argEntity = getTargetEntity(owner.getKey(argRoot + "2"), owner);

    // avoid infinite loops by targeting one's self
    if( argEntity != $null_entity && targetEntity != $null_entity && targetEntity != argEntity )
        targetEntity.addTarget( argEntity );
}


} // end namespace StimResponse

#endif //__DARKMOD_RESPONSE_EFFECTS__

 

 

Edited by VanishedOne

Some things I'm repeatedly thinking about...

 

- louder scream when you're dying

Link to comment
Share on other sites

Thanks! Where do I have to copy that? I have searched for the script-files (for other reasons), but could not find them. They don't seem to have an own pk4-file...

 

@wesp5: Well, as soon as this script is fixed, it should be possible to extinguish the flames, when you copy what I have written in y last post into each lamp you want to extinguish by frobbing it. You can also include it in an earlier entitydef, if you want to include it for a whole group, but I would be careful with that, since you might actually include some lights, you didn't want to...

Link to comment
Share on other sites

Another thing that could be improved: give mappers a way to find stuff in the pk4 files so they know what they have to override if they want to tweak the game in their map.

 

I do have a way to do it that I use myself: I wrote a python script that searches a darkmod installation, looking inside pk4s, both the official ones and in published missions, so I could check for anything that might be affected by stuff that we change. I need to give it a GUI so people can use it without having to mess with python. I'll open a tracker.

 

@ Destined: if you want to change the default behaviour of all maps, your /script/ folder should be in your darkmod folder alongside your /fms/ folder. If you want to change the default scripts only for an FM you are working on, your /script/ folder should be in darkmod/fms/<yourFM>/

Link to comment
Share on other sites

Another thing that could be improved: give mappers a way to find stuff in the pk4 files so they know what they have to override if they want to tweak the game in their map.

 

I do have a way to do it that I use myself: I wrote a python script that searches a darkmod installation, looking inside pk4s, both the official ones and in published missions, so I could check for anything that might be affected by stuff that we change. I need to give it a GUI so people can use it without having to mess with python. I'll open a tracker.

 

@ Destined: if you want to change the default behaviour of all maps, your /script/ folder should be in your darkmod folder next to your /fms/ folder. If you want to change the default scripts only for an FM you are working on, your /script/ folder should be in darkmod/fms/<yourFM>/

 

Yes, that would help. The simple search function of windows does not work for the pk4. If you unzip all (which I have not yet done, only thos I needed), it should work better. I think you can even turn on, in-file search.

 

To be honest, I did not want to make the changes for myself, but wanted to help wesp5 to make them. Although it was quite interesting for me to play around with the mod a bit. But thanks for the info anyway!

 

The final (working) form, that has to be inserted into the def-file looks like this:

 

"frobable" "1"

"sr_class_1" "S"

"sr_type_1" "STIM_FROB"

"sr_state_1" "1"

"sr_class_2" "R"

"sr_type_2" "STIM_FROB"

"sr_state_2" "1"

"sr_effect_2_1" "effect_light_off"

"sr_effect_2_1_arg1" "_SELF"

 

It may be, that there's a simpler way, but with my current knowledge, that is all I could do. So, if anyone wants light entities to be extinguishable by frobbing them, you can just copy the text above and insert it in the curly brackets of the entitiy you want to have this property.

Link to comment
Share on other sites

The final (working) form, that has to be inserted into the def-file looks like this:

Okay, I inserted this for testing purposes into tdm_lights_static.def right at the start in both entityDef atdm:static_light_lit_base and atdm:static_light_unlit_base. Then I copied the file into /script and also tried /def and /script/def but it is not working. The oil lamps are again not even frobable. What am I doing wrong?

 

Update: I tried the same with the lines inserted in all the seperate oil lamp entities, it's still not working! I put the file into tdm_defs01.pk4, still nothing!

Edited by wesp5
Link to comment
Share on other sites

I am not sure, I follow what you did (especially with the /scripts). It sounds as if you copied the def-file into the scripts folder. That will do no good.

But I forgot, that you have to correct the script... So, what you want to do is:

You take the text VanishedOne has posted in the spoilers and replace the whole content of the file \scripts\tdm_response_effects.script with the text. This is needed, so that the "effect_light_off" works.

The part I wrote should be pasted into some curly brackets. If you want it for all static lights, I would try the file "tdm_lights_static.def" and insert in the entry "entityDef atdm:static_light_lit_base". This is the first entry in the file. Try copying it under the line "lightType" "AIUSE_LIGHTTYPE_TORCH"

 

I just checked and it worked for me. You can easily check, if it worked or not: After the changes, try to open DarkRadiant and create an entity: darkmod->Lights->Model Lights, Static and choose any model. If it all worked, you can check the box "Show inherited properties" and there you should find somewhere all the spawnargs that were inserted manually in the def files. As long as these models were used, it should also apply for lights in the game.

Edited by Destined
Link to comment
Share on other sites

Oh, ok, thanks. I have downloaded the file.

It's working now and it's looking great! I think this would be a nice addition to the game giving the player more and realistic options. For now I only changed it for oil lamps, because I don't know how it would look for chandeliers and scones with several candles. Maybe we could do a poll if this should be included into the base game? Especially at it is so easy to add and the script file will be updated anyway...

Edited by wesp5
Link to comment
Share on other sites

Okay, now that the oil lamp fix is working, I want to discuss some other minor issues I noticed while testing it by starting missions over and over again:

 

1. Skipping a mission intro is only possible by using the attack key (or left mouse button?) with no info about this. The FROB key and ESC do not work!

So please either add more options like FROB to do the same or add an info text to the screen like "(Skip with attack key/frob key/left mouse)".

2. When pressing ESC during the intro you end up in the main menu without the option to resume, only restarting is possible. So please either make it

possible to skip the intro with ESC or give the option to resume at the moment we escaped. Right now it just cuts off the intro with no way back!

Link to comment
Share on other sites

One thought arising from the oil lamp spin-off thread: at the moment, if a mapper wants frobable oil lamps or ultra-fast zombies or whatever change to a class, the options are to change entities individually or to package an entityDef with the map. I don't know of any other way to change the spawnargs for an entity class--except via the difficulty settings, for which DR has that convenient editor. The drawback is, you'd have to make the change three times, once for each difficulty level. It would be still more convenient if the 'Difficulty' editor became a 'Map Settings/Difficulty' editor with a fourth 'All/Default' tab.

Edited by VanishedOne

Some things I'm repeatedly thinking about...

 

- louder scream when you're dying

Link to comment
Share on other sites

Here are two more suggestions:

 

xf9kbm.png

1. Being able to place fruit, food, coins or any shiny stuff in the AI visible path as bait to lure the AI into crouch position and then BAM! :D This could be useful if you want the AI to stop in a certain part of the map.

 

2. Being able to store one rat in your inventory (Bag) so you can later place them in a room to lure AI out. This could be useful as an alternative when the AI roams a particular room making it difficult to move around it.

Link to comment
Share on other sites

1. Being able to place fruit, food, coins or any shiny stuff in the AI visible path as bait to lure the AI into crouch position and then BAM! :D This could be useful if you want the AI to stop in a certain part of the map.

 

2. Being able to store one rat in your inventory (Bag) so you can later place them in a room to lure AI out. This could be useful as an alternative when the AI roams a particular room making it difficult to move around it.

 

I like (1). More ways to distract an AI without causing an alert are good. Maybe we could reuse the same mechanism that AI use to inspect a body, but without the alert. Or just get the AI to play the kneel animation, if that covers it.

 

For 2, scaring an AI out of a room might turn out to be too easy unless it causes an alert. It'd be hard to design a challenging map if the player can clear any room without effort.

Link to comment
Share on other sites

One problem with (1) might be: why aren't AI also lured by fruit placed on tables by the mapper, or other 'shiny stuff' lying around? Why haven't they eaten everything and stolen all the easily reached coins before you arrive?

 

Of course, if something like this is ever implemented it might get more plausible:

 

 

Pot, bread, cheese, etc --- AI leans over and makes audible sniffing sound. Short range, 20% chance.

(I'm guessing this is the kind of thing the 'invitation' stim was reserved for, based on its description. But that list is from a decade ago...)

Some things I'm repeatedly thinking about...

 

- louder scream when you're dying

Link to comment
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.


  • Recent Status Updates

    • Ansome

      Turns out my 15th anniversary mission idea has already been done once or twice before! I've been beaten to the punch once again, but I suppose that's to be expected when there's over 170 FMs out there, eh? I'm not complaining though, I love learning new tricks and taking inspiration from past FMs. Best of luck on your own fan missions!
      · 4 replies
    • The Black Arrow

      I wanna play Doom 3, but fhDoom has much better features than dhewm3, yet fhDoom is old, outdated and probably not supported. Damn!
      Makes me think that TDM engine for Doom 3 itself would actually be perfect.
      · 6 replies
    • Petike the Taffer

      Maybe a bit of advice ? In the FM series I'm preparing, the two main characters have the given names Toby and Agnes (it's the protagonist and deuteragonist, respectively), I've been toying with the idea of giving them family names as well, since many of the FM series have named protagonists who have surnames. Toby's from a family who were usually farriers, though he eventually wound up working as a cobbler (this serves as a daylight "front" for his night time thieving). Would it make sense if the man's popularly accepted family name was Farrier ? It's an existing, though less common English surname, and it directly refers to the profession practiced by his relatives. Your suggestions ?
      · 9 replies
    • nbohr1more

      Looks like the "Reverse April Fools" releases were too well hidden. Darkfate still hasn't acknowledge all the new releases. Did you play any of the new April Fools missions?
      · 5 replies
    • The Black Arrow

      Hope everyone has the blessing of undying motivation for "The Dark Mod 15th Anniversary Contest". Can't wait to see the many magnificent missions you all may have planned. Good luck, with an Ace!
      · 0 replies
×
×
  • Create New...