Jump to content
Sign in to follow this  
xxanimusxx

General questions and specific ones concerning mission

Recommended Posts

Hello there Bohemians,

after a long consideration I finally brought myself to register to this very useful forum

in order to ask some questions which are bugging me quite some time now.

I'm a computer science university student in Germany (well you'll notice soon enough while reading my English) and I must say:

the script-syntax used in Arma2 is the most ugly one I've encountered so far :) (No offense to the programmers though!)

The learning curve is very steep but somehow I managed to get a hang of it and building

my own scripts is not that hard anymore (although MP locality confuses me sometimes...).

Okay let's end the introduction and get to the real topic.

I'm here because I have a lot of questions concerning the editing of missions and common Do's and Don'ts

which couldn't be answered by a noob like me but by experienced users.

Here is some short basic data:

I'm in the process of editing a Chernarus-Mission of a (by now well known) Mod for Arma2.

My current approach is to add my stuff in the Arma 2 Editor and merge the output with the mission-pbo from the Mod - which actually works great so far.

As this approach sounds like unnecessary work it is unfortunately the only way because the Mission-pbo is the only

part of the Mod I can legitimately modify. I have no access to any other parts of the Mod or whatsover.

In addition to the Arma2 Editor I also use the RealTimeEditor (by Jonas Scholz) every time

I have to insert Units e.g. in buildings - for placing Triggers and Waypoints I prefer to use the ol' good Arma2 Editor :)

[TABLE=width: 600, align: left]

[TR]

[TD]
Used Arma-Game:
[/TD]

[TD]Arma 2 Combined Operations[/TD]

[/TR]

[TR]

[TD]
Arma2-Version:
[/TD]

[TD]1.62[/TD]

[/TR]

[TR]

[TD]
Beta-Patch:
[/TD]

[TD]1.62.97771[/TD]

[/TR]

[TR]

[TD]
Mods used while Editing with RTE:
[/TD]

[TD]@CBA(_A2/_OA), @JayArma2Lib_new, @RTEditor[/TD]

[/TR]

[/TABLE]

Okay now I want to ask the common questions (which are somehow connected to the mission I want to edit).

  • Triggers
    Like everybody else I also use triggers to put dynamic reactions to player behaviour:


    I placed triggers (Bluefor / repidiately) and Condition: "this" into the entrance of the churches in the map.

    The onAct-field calls a function (
    thisList call fnc_showMessage;
    ) which checks a variable (_this select 0 getVariable...)

    and outputs a message onto the display if this variable is not set. After that the variable will get set and every

    consecutive call of
    fnc_showMessage
    will do nothing - it's just to notice the player
    once
    what he can do in that buildings.

    Unfortunately this happens: Any player of Blufor activates the trigger and the message is shown to all players.

    Changing the Condition to "player in thisList" shows the message only to the player who enters the trigger area,

    but if someone else stepts into the area while another one is still in there, he won't get any message.


    After I read some topics related to this I concluded the following:

    • Triggers inserted within the Editor are MP global, so fulfilling the condition will execute the script given in onAct(ivation) on all machines,
      thus leading to undesirable behaviour if the condition or onAct-Script isn't written to counterbalance.
      One could use the following in the condition field or in the called script: player in thisList
      Unfortunately this leads to another problem: thisList holds all players within the trigger range who fulfilled the condition
      and gets updated when more players are entering the trigger area. If you use to call/execVM a custom made script within the onAct-field,
      one has to constantly loop within the script in order to assign the effects to all players in the trigger (e.g. with {..}foreach _thisList) because
      the trigger is fired after one player has fulfilled the condition - latecomers won't affect the trigger state unless all players have
      left the trigger area.
    • Triggers inserted with createTrigger are local (according to Biki). So activating the trigger by the player
      on whose machine the trigger was created will have the opposite effect of the trigger above: the onAct-field will be
      executed on the players machine only and won't get broadcasted to the other machines.
      thisList select 0 will return the player and count thisList will always return 1.

    Result:

    So to solve my problem I just need to create the triggers script-side (e.g. in init.sqf). The position and other attributes can be copied from

    withing the Editor into the script to match the location.

    Q1: Is this the correct approach?

    As createTrigger is local, there shouldn't be any problems even if the triggers overlap (they

    surely will because the same location is used for all of them), should there?

    [*] Actions

    What I actually want is to add various Actions to playable units but with the condition that the players who actually

    got the actions assigned can't see them.

    Every player should be able to see the actions of the other players, but not their own.

    For example: We have 3 player in the server and the action "Tell me a joke" is added to all players. As common sense

    dictates you should be able to choose "Tell me a joke" if you face another player but to see this option on yourself would

    be... rather... well, socially awkward :)

    According to Biki the addAction command is local, so I can put some code into the init.sqf which will loop all playable

    units and add the actions from the perspective of the current player who loads the mission. This will ensure that the current

    player won't get to see this action on himself for the simple reason that there is no code adding that specific action

    to the player on his machine.

    The problem: If a player joins later on or reconnects the method described above will fail because the current player has already

    initialized the mission. Surely there is the [] spawn {loop ... sleep}-Method but I want to dissociate myself from

    doing so because I think that the aforementioned method is the least effective in regards of ressources and script logic.

    Q2: Is there a way to solve this problem? Just thinking about using a PVEH to check if the new player has the action

    in order to add it gives me the chills... But I won't resist if this is the best solution though.

    [*]Tasks

    • Using createSimpleTask one can create Tasks which can be assigned to players. This command is labeled as Global in Biki.
      Q3: What does that mean in this context? Normally you'd execute somethink like:
      _myTask = player createSimpleTask["myTask"];


      This will normally add the task (after additional commands and setCurrentTask) to the player. As the other task-commands
      seem to be local, does that mean executing createSimpleTask will create that Task on every machine but every player can
      set the tasks and taskstate for themself without changing the states globally for that specific task?
      So what happens if someone succeeds or removes a task? Is this broadcasted to every machine or is that local?

    • Sub-Tasks
      One can assign Sub-tasks to a parent task with the following lines of code:
      _task = player createSimpleTask["myTask"];
      _task setSimpleTaskDescription ["To learn more about Arma Editing", "The Super-Task", ""];
      _task setTaskState "Created";
      
      _otherTask = player createSimpleTask["myOtherTask", _task];
      _otherTask setTaskState "Assigned";
      player setCurrentTask _otherTask;
      [...]


      For some reason _otherTask is aligned just under the Parent-Task without any context as beeing the Sub-Task. This could also be
      a misunderstanding because I never did see a sub-task for myself before but I expected at least some sort of indention to show that
      _otherTask ist actually a subclass.
      Q4: What did do I wrong here?
      I also read that succeeding the parent task will succeed the subtasks automatically, but what does happen when all the sub-tasks
      are succeeded? Will the parent task succeed when all the subtasks also succeeded? Or do I have to set the parent tasks' state manually?

    • TaskHint
      I don't know why but calling
       [objNull, ObjNull, _myTask, "SUCCEEDED"] execVM "CA\Modules\MP\data\scriptCommands\taskHint.sqf";


      doesn't do anything! There isn't even a script error, nothing happens in particular. Is this supposed to be?
      I know that there is a taskHint command and it's fairly easy to use, but I wanted to see what this script actually does...

Okay then, these were my "common" questions for the problems I encountered so far. I'm sure that I need to ask much more questions after these

but this will suffice for the time being.

So what am I trying to accomplish?

I'm adding some kind of RPG-System into my Chernarus-Mission which is influenced by a game series that is somewhat close to the storyline

of the Mod I'm using. If you wan't to know the Mod's name by now, it is... DayZ. I know I know, there are already enough forums dealing with

that already but I immersed myself into learning Arma 2 Editing and the actual Mod doesn't really matter at this time.

There are several more things I want to know like Camera-Editing and such but I'll read into that before I actually ask some questions as the

knowledge base of this particular topic is quite big.

Okay folks, that's it for now.

I hope you didn't "t/l;d/r"'d my topic and took your time to get acquainted with my chains of thoughts. It's really sufficient if you can deliver

a link to the questions so I can look into or just some short sentences which could lead me to the right track.

I'm fairly new to this whole business so prepare to get asked more frequently from now on :)

In regards,

Animus

Share this post


Link to post
Share on other sites

Triggers:

I would use the following trigger settings:

NOT REPEATABLE

ANYBODY PRESENT

Condition: player in thisList

On Act: [player] call fnc_showMessage;

If 'player in thisList' is true then we know that the local player object is in the zone, then why not just call the script with the player object?

Action:

Instead of adding the action to everybody else, just add it to the the local player:

waitUntil {!isNull player};
//If you use CBA recommend you use the CBA_fnc_playerAction (named something like that). Otherwise you have to readd the action on respawn.
player addAction ["Tell a joke", "tell_joke.sqf", [], 0, false, true, "", "{isPlayer _x} count ((getPos _this) nearObjects ['CAManBase', 3]) > 1"];

Notice the last part of the statement. This part figures out how many units are within 3m:

((getPos _this) nearObjects ['CAManBase', 3])

Note that the player itself is within 3m of himself!!. Lets call the result THE_NEAR_UNITS, then the expression:

{isPlayer _x} count THE_NEAR_UNITS > 1

That counts how many objects in the array are players. If there are 2 or more then the expression is true. When the expression is true then the action is available, and vica versa. Remember the player the action is attached to is included in the array so we need another human player, thus > 1.

Task:

The BIKI says that the argument to createSimpleTask can be global and that the effect is global. I'm pretty sure only the first is true. I recently tried to exploit the "effect is global" - and my conclusion what that the effect is only local. It is also used like a local command in all the (working) task management scripts I've seen.

Share this post


Link to post
Share on other sites

[*] Triggers inserted within the Editor are MP global, so fulfilling the condition will execute the script given in onAct(ivation) on all machines,

thus leading to undesirable behaviour if the condition or onAct-Script isn't written to counterbalance.

Hmm no, the trigger will exist on all machines but they still run locally. One trigger with condition this and blufor present will be true on all machines (note: very small time difference). However, "player in thisList" can only be true for non-dedicated machines (player is a null-object on dedicated servers), and it is only true on the machine where the variable player (the client itself) is in the list of the trigger.

Share this post


Link to post
Share on other sites
Triggers:

I would use the following trigger settings:

NOT REPEATABLE

ANYBODY PRESENT

Condition: player in thisList

On Act: [player] call fnc_showMessage;

If 'player in thisList' is true then we know that the local player object is in the zone, then why not just call the script with the player object?

Well that seems reasonable :)

My problem was that if more than one person is in the trigger the other persons stepping into the trigger zone didnt get any message shown.

On the other hand I had another trigger which would just attach an action to the person who is in the trigger zone and it did work - but somehow all the other players in the server also did get the action attached to themselfs, so I was somewhat confused.

I'll try this and report back :)

Action:

Instead of adding the action to everybody else, just add it to the the local player:

waitUntil {!isNull player};
//If you use CBA recommend you use the CBA_fnc_playerAction (named something like that). Otherwise you have to readd the action on respawn.
player addAction ["Tell a joke", "tell_joke.sqf", [], 0, false, true, "", "{isPlayer _x} count ((getPos _this) nearObjects ['CAManBase', 3]) > 1"];

Notice the last part of the statement. This part figures out how many units are within 3m:

((getPos _this) nearObjects ['CAManBase', 3])

Note that the player itself is within 3m of himself!!. Lets call the result THE_NEAR_UNITS, then the expression:

{isPlayer _x} count THE_NEAR_UNITS > 1

That counts how many objects in the array are players. If there are 2 or more then the expression is true. When the expression is true then the action is available, and vica versa. Remember the player the action is attached to is included in the array so we need another human player, thus > 1

Okay if I understand this right this will show the Action on the local player if anybody else approaches him - but the action will be shown to the local player, not to the one approaching him, right?

I mean the effect of addAction is not global, so the other machines don't know about this action attached to the local player.

That's an interesting approach but I see one potential problem here: let's say there is a player near me (<= 3m) I'll get the action added to the local player. So if I choose "Tell me a joke" the .sqf-Script will be executed and 4 parameters delivered - the first two of them containing who activated the Action and on whom the Action is attached. In this case both parameters will be identical because the action is attached to the local player in addition that the local player activated that action on himself, so I loose the opportunity to actually identify the person I wanted to hear the joke from :)

Well I could get the player in the script with (getPos player) nearEntities ["Man", 3] but if there are more than one person which met the criteria above it will be impossible to distinct the right person.

The scenario with the joke telling is a simple example but I want to know who activated the action on the player in order to process some data - like for example an action in order to steal something from within the inventory: the player approaches another one and chooses "steal something", so I can get the inventory of the player who is robbed and randomly take an item away.

Do I misunderstand something here? :<

Task:

The BIKI says that the argument to createSimpleTask can be global and that the effect is global. I'm pretty sure only the first is true. I recently tried to exploit the "effect is global" - and my conclusion what that the effect is only local. It is also used like a local command in all the (working) task management scripts I've seen.

Thanks for the insight, I'll keep that in mind.

Actually did you ever use CA\Modules\MP\data\scriptCommands\taskHint.sqf ?

Share this post


Link to post
Share on other sites

Seems I misunderstood. I though you wanted to tell the other person a joke - not be told a joke from the other person.

While the "correct" method would be to add the action to everybody else on all machines, including to take care of JIP clients, sometimes a more practical method is far more simpler. There is a command cursorTarget which gives the object the player is currently looking at (wouldn't surprise me if this is actually used to figure out the actions to show based on what the player is looking at by the engine itself).

So maybe the following addaction condition could be used:

cursorTarget distance _this < 3 and cursorTarget isKindOf 'CAManBase'

You could even add:

and cursorTarget getVariable ['IsFunnyGuy', false]

If you only want some people to be funny.

Then in the script .sqf file you could just read the cursorTarget again figure out who you were talking to. Also I recommend you use CAManBase instead of Man. Try looking at this "tree-graph":

http://community.bistudio.com/wiki/ArmA_2:_CfgVehicles#Man_Class_Vehicles

Note where, the Man, Animal and CAManBase class is. So unless you want to hear jokes from farm animals then I recommend you use CAManBase. But, to each, their own :).

I never used the script taskHint.sqf. But I have used the command taskHint :)

Edited by Muzzleflash

Share this post


Link to post
Share on other sites
Seems I misunderstood. I though you wanted to tell the other person a joke - not be told a joke from the other person.

While the "correct" method would be to add the action to everybody else on all machines, including to take care of JIP clients, sometimes a more practical method is far more simpler. There is a command cursorTarget which gives the object the player is currently looking at (wouldn't surprise me if this is actually used to figure out the actions to show based on what the player is looking at by the engine itself).

So maybe the following addaction condition could be used:

cursorTarget distance _this < 3 and cursorTarget isKindOf 'CAManBase'

You could even add:

and cursorTarget getVariable ['IsFunnyGuy', false]

If you only want some people to be funny.

Then in the script .sqf file you could just read the cursorTarget again figure out who you were talking to. Also I recommend you use CAManBase instead of Man. Try looking at this "tree-graph":

http://community.bistudio.com/wiki/ArmA_2:_CfgVehicles#Man_Class_Vehicles

Note where, the Man, Animal and CAManBase class is. So unless you want to hear jokes from farm animals then I recommend you use CAManBase. But, to each, their own :).

I never used the script taskHint.sqf. But I have used the command taskHint :)

Ahaha yeah, I wondered before why I get animals in my result array x'DD

I also thought about using the cursorTarget-approach but wasn't sure if this would be practical, but thinking about it twice it seems to be a neat solution rather than doing all the work for JIP client and synchronizing 'n stuff :)

Well now there is still my problem with Sub-Tasks... can someone provide a working script with sub-tasks to a parent-task? I don't know if it's just me or the task display is just supposed to show it like that but I don't have the feeling that my tasks are beeing grouped under my parent task :S

I attached an image showing the tasks I created:

arma2oatasks.png

Is this really supposed to look like this? :<

Share this post


Link to post
Share on other sites

Well I'd like to see that too. I read some stuff regarding parent Tasks and child tasks and stuff, and honestly I did not understand shit.

But yeah, from what I gathered, child Tasks should appear just under their parent Task. I don't think there's any kind of indentation or anything (which I guess is what you'd expect?).

Share this post


Link to post
Share on other sites
Well now there is still my problem with Sub-Tasks... can someone provide a working script with sub-tasks to a parent-task? I don't know if it's just me or the task display is just supposed to show it like that but I don't have the feeling that my tasks are beeing grouped under my parent task :S

I attached an image showing the tasks I created:

I think that is how it is "supposed" to look.

Normally when you add a task, the most recently added is at the top. However, if you add them as subtask they show below as you can see. However, if you add more subtasks then the latest subtask is the topmost one. Given, that there is no indentation and no simple way to add another subtask below the others, basically makes subtask useless imo. If you add a subsubtask SSB "under" another subtask SB then the SSB is above SA but under SB. Not that it adds much value, except giving the opportunity for top-down ordering. by making every task a subtask of the previous task. Might get into trouble though when you marks the first task (the parent of all other tasks) as completed.

Share this post


Link to post
Share on other sites

Okay after some time spent on trying things out I managed to write a simple function which indents the subtasks somehow.

The outcome will look like this:

arma2oacustomtask.png

I tried to use some cool chars like └ or ├ but these got replaced with a whitespace although I used toString and UTF8 'n shit....

I don't know if this is of any use for you guyz but I'll post the code anyway :)

TASKS_fnc_addTask = {
private ["_player", "_taskName", "_taskTitle", "_taskDescription", "_taskMarker", "_taskMarkerName", "_taskMarkerPos", "_parentTask", "_taskObj", "_taskParams"];

_player 			= 	_this select 0;	// The player who gets the task
_taskName 			= 	_this select 1;	// The Task-Name (not the title! Will be used to identify the task)
_taskTitle 			=	_this select 2;	// Title of the task to show in diary
_taskDescription	=	_this select 3;	// Description of this task

// Now comes the optional parameters

_taskMarker			=	[];		// Array containing Marker-Title and Marker-Position
if (count _this > 4) then 
{
	_taskMarker 	= 	_this select 4;
};

_taskParams			=	[_taskName];
_parentTask			=	taskNull;		// Parent-Task to which this task should be added to
if (count _this > 5) then 
{
	_parentTask 	= 	_this select 5;
	_taskParams 	set [count _taskParams, _parentTask];
};

_taskMarkerName 	=	"";
_taskMarkerPos		=	[];

if (count _taskMarker > 0) then
{
	_taskMarkerName = 	_taskMarker select 0;
	_taskMarkerPos	=	_taskMarker select 1;
};

_taskObj 			=	_player createSimpleTask 	_taskParams;

if (!isNull _parentTask) then
{
	// Get the level of this child
	_level 	= 0;
	_indent	= "";
	_parent = _parentTask;

	while {!isNull _parent} do
	{
		_level 	= _level + 1;

		if (_level > 1) then
		{
			_indent = _indent + "  ";
		};

		_parent	= taskParent _parent;
	};

	// Insert the indention
	_indent 	= _indent + "|- ";
	_taskTitle 	= _indent + _taskTitle;
};

_taskObj				setSimpleTaskDescription	[_taskDescription, _taskTitle, _taskMarkerName];

// Add the Destination-Info if there is one
if (count _taskMarkerPos > 0) then
{
	_taskObj			setSimpleTaskDestination	_taskMarkerPos;
};

_taskObj;
};

Here is the sample Code which leads to the output above:

_notSoIMportant					= [player, "none", "Nothing to see here", ""] call TASKS_fnc_addTask;
_notSoIMportant	setTaskState "Failed";

_superTask 					= [player, "MySuperTask", "Shopping", "I need some stuff from the market!"] call TASKS_fnc_addTask;
_breakfast					= [player, "breakfast", "Breakfast", "Some stuff for the breakfast", [], _superTask] call TASKS_fnc_addTask;
	_breakfast_bacon 		= [player, "breakfast_bacon", "Bacon", "All the bacon you can get. I said ALL!", [], _breakfast] call TASKS_fnc_addTask;
		_breakfast_bacon_all    = [player, "breakfast_bacon_all", "Get 'em all!", "All the bacon you can get. I said ALL!", [], _breakfast_bacon] call TASKS_fnc_addTask;
	_breakfast_eggs 		        = [player, "breakfast_eggs", "Eggs", "Fetch me 6 Eggs, will you?", [], _breakfast] call TASKS_fnc_addTask;
_bbq						= [player, "barbecue", "Barbecue", "Let's grill!", [], _superTask] call TASKS_fnc_addTask;
	_bbq_steaks			= [player, "barbecue_steaks", "Steaks", "MEEEAT!", [], _bbq] call TASKS_fnc_addTask;
	_bbq_lettuce			= [player, "barbecue_lettuce", "Lettuce", "Wth?!", [], _bbq] call TASKS_fnc_addTask;

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×