Back to the Korax Forum Archives


Forum

Instructions on creating a new ACS function (action special)

Tue, 27 Jun 2006 09:01:24

Crimson Wizard

First of all I want to quote myself from what I wrote on my project's page; that is about using large ACS command ID.
All the action specials that I added to the mod can be used only in scripts. That is because linedef cannot use action of Id > 255, and most of the Ids between 1 and 255 are already in use. So I just gave my action specials high Ids to avoid possibility of conflicts in case Vavoom will have updated action specials list in future versions.
I add, that since the size of ACS command's id is a property of the Hexen map, not Vavoom, it cannot be changed, at least easily. So, how to use new action specials then? The only way I could imagine is to use them thru scripts. For example, if you have a switch which you want to commit your new action when player "uses" it, you should tag ExecuteACS to that switch and call your new action special in corresponding script. How to make a new action special. [color=red:3pe59xwb]--------- this part of explanation is a bit incorrect, see Janis Lengzdish'es comment below ------[/color:3pe59xwb] 1. In 'common/Object.vc' insert your new special Id in the list of line specials. for example:
.......
	LNSPEC_DoorCloseWaitOpen = 249,
	LNSPEC_FloorDonut,// 250
	LNSPEC_FloorAndCeilingLowerRaise,
	LNSPEC_CeilingRaiseToNearest,
	LNSPEC_CeilingLowerToLowest,
	LNSPEC_CeilingLowerToFloor,
	LNSPEC_CeilingCrushRaiseAndStaySilentA,

>>>>	MYNEWSPECIAL = 1000,
	LNSPEC_Max
};
[color=red:3pe59xwb]--------- edn of incorrect part of explanation ------[/color:3pe59xwb] 2. Create a corresponding function which will handle your new special. It may be a member of ?LevelInfo, MainGameInfo, Player, Actor or whatever class derived from Actor (and maybe some other, but I am not sure). Choose what you think is most logical according to what this special is doing. 3. In 'progs/game/?LevelInfo.vc' find ExecuteActionSpecial() function with a lengthy switch statement and place there code which will call your newly created function incase your new action special is executed. For example:
case MYNEWSPECIAL:
	buttonSuccess = MyNewFunc(Arg1, Arg2, Arg3, Arg4, Arg5);
	break;
In this case MyNewFunc belongs to ?LevelInfo class. If it belongs , for example, to Actor class, use following form:
case MYNEWSPECIAL:
	if (A)
	       buttonSuccess = A.MyNewFunc(Arg1, Arg2, Arg3, Arg4, Arg5);
	break;
Ofcourse your code may be slighly different depending of how your function(s) work. I put here fragment from HexenLevelInfo.vc of my project to show what it may look like.
case SPEC_RPG_GrantPlayerAttribute:
	// This must be player, and he must be alive
	if (A && A.bIsPlayer && A.Player.PlayerState != PST_DEAD)
	{
		buttonSuccess = true;
		A.Player.UH_GrantPlayerAttribute(Arg1);
	}
	break;
case SPEC_RPG_ForceAddPlayerAttribute:
	// This must be player, and he must be alive
	if (A && A.bIsPlayer && A.Player.PlayerState != PST_DEAD)
	{
		buttonSuccess = true;
		A.Player.UH_ForceAddPlayerAttribute(Arg1, Arg2, Arg3, Arg4);
	}
	break;
case SPEC_RPG_ForceSubtractPlayerAttribute:
	// This must be player, and he must be alive
	if (A && A.bIsPlayer && A.Player.PlayerState != PST_DEAD)
	{
		buttonSuccess = true;
		A.Player.UH_ForceSubtractPlayerAttribute(Arg1, Arg2, Arg3, Arg4);
	}
	break;
case SPEC_RPG_GrantPlayerExperience:
	// This must be player, and he must be alive
	if (A && A.bIsPlayer && A.Player.PlayerState != PST_DEAD)
	{
		buttonSuccess = true;
		A.Player.UH_GrantPlayerExperience(Arg1);
	}
	break;
case SPEC_Pawn_ChangeTeam:
	if(Arg1 > 0)
	{
		buttonSuccess = UH_ChangePawnTeam(Arg1, Arg2, none);
	}
	// This must be Pawn (it may be dead though)
	else if(A && A.IsA('Pawn'))
	{
		buttonSuccess = UH_ChangePawnTeam(0, Arg2, A);
	}
	break;
case SPEC_Actor_SetTaggedDest:
	if(Arg1 > 0)
	{
		buttonSuccess = UH_SetActorTaggedDest(Arg1, Arg2, none);
	}
	else if(A)
	{
		buttonSuccess = UH_SetActorTaggedDest(0, Arg2, A);
	}
	break;
case SPEC_Thing_3dThrust:
	if(Arg1 > 0)
	{
		buttonSuccess = UH_Thing3dThrust(Arg1, Arg2, Arg3, Arg4, none);
	}
	else if(A)
	{
		buttonSuccess = UH_Thing3dThrust(0, Arg2, Arg3, Arg4, A);
	}
	break;
case SPEC_Thing_Damage:
	if(Arg1 > 0)
	{
	   buttonSuccess = UH_ThingDamage(Arg1, Arg2, Arg3, none);
	}
	else if(A)
	{
	   buttonSuccess = UH_ThingDamage(0, Arg2, Arg3, A);
	}
	break;
(Notice, that some of my specials above can be called either for exact, tagged objects or objects, that triggered line special (crossed the line, toggled switch, etc).
Tue, 27 Jun 2006 13:43:50

Firebrand

Just what I needed! <!-- s:lol: --><img src="{SMILIES_PATH}/icon_lol.gif" alt=":lol:" title="Laughing" /><!-- s:lol: --> I'll read it calmly soon, right now I'm in a rush, heh!
Tue, 27 Jun 2006 19:26:26

dj_jl

Please, don't add your constants to Object.vc, instead put them in your game classes, in this case best place will be ?LevelInfo.vc.
Tue, 27 Jun 2006 19:37:44

Crimson Wizard

Well, yes, now I know that, thanks. <!-- s:) --><img src="{SMILIES_PATH}/icon_smile.gif" alt=":)" title="Smile" /><!-- s:) -->
Sat, 09 Dec 2006 14:37:07

Crimson Wizard

Modified ACS compiler which allows Action Specials Id > 255 is here: <!-- m --><a class="postlink" href="http://downloads.orcishweb.com/koraxdev/vavoom/acc.zip">http://downloads.orcishweb.com/koraxdev/vavoom/acc.zip</a><!-- m -->

Back to the Korax Forum Archives