Mjjstral

Members
  • Content count

    78
  • Joined

  • Last visited

Community Reputation

21 Excellent

About Mjjstral

  • Rank
    Lance Corporal

Contact Methods

Profile Information

  • Gender
  • Location
    Germany
  • Interests
    philosophy, border science, science fiction

Command & Conquer Profile

  • Favourite C&C
    Kanes Wrath

Recent Profile Visitors

876 profile views
  1. A lazy workaround: Growth Accelerators fire weapon on same type and same team (excluded self) in a narrow range around them to eliminate duplicates with a special death type. Use a random delay between shots. Duplicates create an object on that special death type that creates the monetary compensation. If it has to do with the tiberium field you could replace it with an unbugged version via lua easily on map start automatically (I can explain if needed).
  2. The name of the parameters doesn't matter, what matters is the actual data type that lies behind them. That means you can rename self to whatever you like. Self is a lua table type, spySelf must also be a lua table, as all ScriptEvents given object arguments are. Everything that follows is very likely a string. You can test what lies behind these parameters when you display arg[3] and arg[4] ... To test the type just display type(arg[3]). You can also define the whole function header with three dots like that: function OnExampleSpyMoving(...) That doesn't limit the number of arguments if you don't know how many you get, but then you are limited to access them only with arg[NumberOfArgument]. Hope that helps.
  3. A workaround would be to call the map scripts that have a player parameter from lua with this special command: ExecuteAction("TEAM_EXECUTE_SEQUENTIAL_SCRIPT_LOOPING","/team",MapScriptName,1) If we set the player in the map script to <this player> then we can even choose the player by changing "/team" to the team of that player. This is a very neat trick. And in KW we can insert a map script into ALL official maps in one move by adding it to a library map (lib_mg_tacticalplay_skirmish).
  4. Basically a ScriptedEvent is the only event type that can be triggered directly within lua code, hence the name. You can trigger a scripted event with these commands: ObjectBroadcastEventToEnemies(object,eventname,radius) ObjectBroadcastEventToAllies(object,eventname,radius) ObjectBroadcastEventToUnits(object,eventname,radius) ObjectBroadcastEventToCivilians(object,eventname,radius) ObjectDispatchEvent(object,eventname,radius) HordeBroadcastEventToMembers(?) So if you call for example ObjectBroadcastEventToEnemies(self,"ExampleSpyMoving",1000) you trigger the functions of all units that have this event in their eventlist. Like this: <EventList Name="SpyFunctions" Inherit="BaseScriptFunctions"> <EventHandler EventName="ExampleSpyMoving" ScriptFunctionName="OnExampleSpyMoving" DebugSingleStep="false"/> </EventList> It calls the function OnExampleSpyMoving(self, other, string) ... If you match the radius parameter with the view radius of the unit it actually makes sense. So the spy could trigger the broadcast when he has the ModelConditionEvent +Moving for example and by that inform all units surounding him about his intention. I also have no idea about ObjectSpy(). Maybe it trigger OnGenericEvent ? We need to test...
  5. Just to motivate all of you: C&C is not dead, not even close to dead. As it is digitally available on Origin and Steam and will be in the future it's a completely different situation nowadays. Proof ? Let's see how many active players we had in the last two weeks just on steam: C&C 3 Tiberium Wars: 16,240 C&C 3 Kane's Wrath: 11,877 C&C Red Alert 3: 21,572 C&C Red Alert 3 Uprising: 10,907 C&C 4: 1,697 That makes a total of 62,293 active players just for these 5 games on steam and only in the last two weeks, not including all the players in offline mode. Overall there are 2,027,084 players and a total of 2,642,506 owners on steam and it's getting more and more and will never stop as long as steam exists. All the Origin and CD/Crack players not even included in this sum. The thing is forums like this feel kind off dead sometimes because most of the discussions have shifted to steam group forums (each game has it's own community hub there). And there is also reddit. And if people say C&C is dead because there is no sequel from EA, then I'll ask you is classical music from Mozart dead because it is hundreds of year old ? C&C already belongs to the digital history of mankind and this forum too to a certain degree.
  6. Use this (You don't even need GetObj.String here I think): ExecuteAction("UNIT_SET_TEAM",GetObj.String(other),GetTeamName(self)) Or this, depending on who's self and who's other: ExecuteAction("UNIT_SET_TEAM",GetObj.String(self),GetTeamName(other)) Also use this to flash the unit for testing (very usefull): ExecuteAction("NAMED_FLASH_WHITE", self, 2) Needed dependencies: function GetTeamName(teamobject) local TeamName = "" local TeamDescription= "" if type(teamobject) == "string" then TeamDescription = ObjectTeamName(GetObj.Table(teamobject)) else TeamDescription = ObjectTeamName(teamobject) end local TeamNumber = gsub(TeamDescription, "%a+%p+", "") if TeamNumber == nil then return error("no team found") --"unknownTeam" end if strfind(TeamDescription, "SkirmishTeamPlayer") ~= nil then --"Player_2/defaultSkirmishTeamPlayer_2" TeamName = "Player_" .. TeamNumber .. "/defaultSkirmishTeamPlayer_" .. TeamNumber .. "" return TeamName elseif strfind(TeamDescription, "teamPlayer") ~= nil then --"Player_1/teamPlayer_1" TeamName = "Player_" .. TeamNumber .. "/teamPlayer_" .. TeamNumber .. "" return TeamName elseif strfind(TeamDescription, "Civilian") ~= nil then --"PlyrCivilian/teamPlyrCivilian" TeamName = "PlyrCivilian/teamPlyrCivilian" return TeamName elseif strfind(TeamDescription, "Creeps") ~= nil then --"PlyrCreeps/teamPlyrCreeps" TeamName = "PlyrCreeps/teamPlyrCreeps" return TeamName elseif strfind(TeamDescription, "teamPlyr") ~= nil then --"PlyrNOD/teamPlyrNOD" TeamName = strsub(TeamDescription, 5, -1) .. "/" .. TeamDescription .. "" return TeamName elseif strfind(TeamDescription, "SkirmishTeam") ~= nil then --"Nod_Enemy_Main/defaultSkirmishTeamNod_Enemy_Main" TeamName = strsub(TeamDescription, 20, -1) .. "/" .. TeamDescription .. "" return TeamName elseif strfind(TeamDescription, "/team") ~= nil and strlen(TeamDescription) == 4 then --"/team" for neutrals TeamName = "/team" return TeamName else TeamName = gsub(strsub(ObjectDescription(teamobject),strfind(ObjectDescription(teamobject), "player ")+10),"%p","") .. "/" .. TeamDescription .. "" return TeamName end end function GetObj.Table(object) if type(object) == "table" then return object else for k,v in globals() do if strfind(k,"ObjID") ~= nil and strfind(ObjectDescription(v),object) then return rawget(globals(),k) end end return object end end
  7. 1. Via dummy object that shots emp effect weapon with very little radius or via lua with ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Enabled", 0) or ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Powered", 0) in combination with a script timer. 2. Create lua object list filtered by object type and give veterancy via ExecuteAction("UNIT_GIVE_EXPERIENCE_LEVEL", ObjectStringName, ExperienceLevelTemplateName) 3. Spawn speical power provider dummy. The special power then also creates a killer dummy that kills itself and the provider. 4. Your solution. 5. We cannot directly know how much power the player has (scripts unusable). An overcomplicated solution could be to calculate the energy production - consumption manually via lua object lists + power events lua calculation coroutine. We can only know directly if one of these events happened in the last n seconds: "BuildingManuallyPoweredDown","BuildingManuallyPoweredUp","LowPower" (Use EvaluateCondition("HAS_EVA_EVENT_PLAYED_IN_LAST_N_SECONDS",EvaEvent,TimeIntervall) for that) 6. Via a dummy that provides an invisible special power that costs money. This SP gets executed via lua. I'll do that in meta mod to reset the credits for some gamemodes and handle credit income then only by scripts (sidenote: tiberium fields can also be removed permanently from the map). 7. Scripts not usable to know the amount of credits. We can only get to know the start ressources or if one of these events happened: "BuildQueuePausedDueToFunds","CannotRepairDueToFunds","CannotUsePowerDueToFunds" (Use EvaluateCondition("HAS_EVA_EVENT_PLAYED_IN_LAST_N_SECONDS",EvaEvent,TimeIntervall) for that) Of course you can write your own lua coroutine that calculates the credits manually (very complicated but not impossible) 8. That's very possible. See meta mod function CountObjectTypeOfTeam(ObjectType,team). Usage example to display would be something like: ExecuteAction("SHOW_MILITARY_CAPTION", "Vehicles: " .. CountObjectTypeOfTeam("VEHICLE","Player_1/teamPlayer_1"),10). You can also display the counts via a typical counters and hide them after n seconds via script timer. 9. You can spawn an invisible unnattackable dummy on each enemy unit that has a little sight radius via lua meta mod special spawn functions. 10. No idea. The script won't work (they all depend on the player parameter, which is unusable atm). 11. Your solution or ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Powered", 0) applied on the radar providing structure temporarily via script timer. 12. ExecuteAction("NAMED_SET_SPECIAL_POWER_COUNTDOWN",...) or one of the other countdown scripts. 13. Your solution or via lua by creating an object table and using one or more parts of this: function DisableObject(object) local Status = {"NO_ATTACK","UNSELECTABLE","NO_COLLISIONS","UNATTACKABLE","CANNOT_BE_SOLD","IN_STASIS","IGNORE_AI_COMMAND","USER_PARALYZED","POWERED_DOWN_EMP","TEMPORARILY_DEFECTED"} for i=1,getn(),1 do ObjectSetObjectStatus(GetObj.Table(object),Status[i]) end ExecuteAction("NAMED_SET_HELD", object, 1) ExecuteAction("NAMED_SET_STRICT_CONTROL_ENABLED", object, 1) ExecuteAction("NAMED_SET_SLEEP_STATUS", object, 1) ExecuteAction("UNIT_SET_STANCE", object, "HOLD_POSITION") ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Enabled", 0) ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Indestructible", 1) ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Selectable", 0) ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Player Targetable", 0) ExecuteAction("UNIT_AFFECT_OBJECT_PANEL_FLAGS", object, "Unsellable", 1) ObjectForbidPlayerCommands(GetObj.Table(object),true) end 14. Very possible. I'll do that in meta mod via a diplomacy menu option where you can toggle control for allied units. The function used for that is TemporaryMergeTeam(team1,team2,forcemerge). To toggle back you can use a script timer that calls the function again after n seconds. The function will toggle the units team automatically back. An example to use a script timer: SetScriptTimer(10,'ExecuteAction("SHOW_MILITARY_CAPTION","Hello World!",5 '). It takes a string and even a function for the second parameter. So except for number 10 everything is somehow doable from my point of view.
  8. However you want to do in the end, here some more input: For giving a specific veterancy level to a unit you can use ExecuteAction("UNIT_GIVE_EXPERIENCE_LEVEL", ObjectStringName, ExperienceLevelTemplateName) For experience templates look into the ExperienceLevels.xml from the C&C3 modsdk source code. In meta mod I made this function (copy code dependencies if you want to use it): function SetObjectsRank(object,rank,objecttype) if objecttype == nil then objecttype=GetObj.Type(object) end ExecuteAction("UNIT_GIVE_EXPERIENCE_LEVEL",GetObj.String(object),objecttype .. ExperienceLevel_ .. rank) end There is also: ObjectCapturingObjectPlayerSide(object) --if not captured before returns nil, so test if ~= nil ObjectTeamName(object) --to associate veterancy production building with a team, store each b. into a table OnCreate For removing player upgrades there is of course ExecuteAction("REMOVE_PLAYER_UPGRADE",...) but we still have no way of using the player parameter for scripts without tricks. Same goes for EvaluateCondition("NAMED_OWNED_BY_PLAYER",GetObj.String(self),PlayerName) But you can use: <RemoveUpgradeUpgrade id="ModuleTag_RemoveUpgradeUpgrade_01"> <TriggeredBy>Upgrade_TestUpgrade1</TriggeredBy> <UpgradeToRemove>Upgrade_TestUpgrade2</UpgradeToRemove> </RemoveUpgradeUpgrade> <RemoveUpgradeUpgrade id="ModuleTag_RemoveUpgradeUpgrade_02"> <TriggeredBy>Upgrade_TestUpgrade2</TriggeredBy> <UpgradeToRemove>Upgrade_TestUpgrade1</UpgradeToRemove> </RemoveUpgradeUpgrade> And then use lua event OnDestroyed and trigger ObjectGrantUpgrade(self, "Upgrade_TestUpgradeX").
  9. This is strange. I mean regardless of how it is attacking, it must trigger the preload event and if it gets support towers then there must be a weapon fired on it for each tower. You don't need the NodObelisk_RELOADING(self) function anymore by doing the support via special power. I have to look over the whole code again maybe. Try to change the MaximumSupportDistance first. There is actually that line if getn(ObjectList)<2 then return end that should prevent such cases..hm
  10. for i=2,getn(ObjectList),1 do ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(ObjectList[i]),"SpecialPower_PrismForwarding",GetObj.String(SupportConnection[tostring(ObjectList[i])])) -- ExecuteAction("NAMED_STOP",ObjectList[i]) -- ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])]) end
  11. Ah sorry bracket was't closed (syntax error): function OnReallyDamaged(self) --add the lua event to scriptevents.xml too if PassengerTable[tostring(self)] == nil then return end for i=1,getn(PassengerTable[tostring(self)]),1 do ExecuteAction("NAMED_EXIT_ALL",PassengerTable[tostring(self)][i]) ExecuteAction("UNIT_AI_TRANSFER",PassengerTable[tostring(self)][i],1) --enable ai in case it was disabled end PassengerTable[tostring(self)]=nil end Important: Put the error function I gave you above all custom code, because if there is a syntax error above it doesn't even get loaded!
  12. This is really interesting and yes this will also probably solve your problem with ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",...) in the other thread. I think at least the argument for other must be a string named object. Good to know.
  13. Yes but the problem of changing the fps to a higher value was that the animation and overall game speed also speeded up resulting in way too fast gameplay. Now we can have just more fps without these negative sideeffects. They can be in both, but you said " in addition to spawn crates". Via ticker box, in skirmish menu you can only do it by replacing the crates option box (as done in meta mod tw and kw version already). Adding a completely new ticker box is not possible by regular ways of modding because it's hardcoded. So we have to use what we have. (random thought here: via binary logic we could make 4 options out of 2, in the heading we write an explanation with all combinations and results) Yes. In meta mod I use multiple ways of enabling/disabling options just for convenience. In multiplayer it will only use number 2 (future) and in skirmish number 2,4 and 5 all simultanously. The most convenient solution obviously is via ticker box. So 2 is the best universal solution and a ticker box replacement is best for pure single player skirmish.
  14. If someone wants to try and report, we can deal with gates in lua too in a very convenient way: ExecuteAction("GATE_OPEN",self) ExecuteAction("GATE_CLOSE",self) ExecuteAction("GATE_READY",self) EvaluateCondition("GATE_IS_OPEN",StringSelf) function GetObj.String(object) --for StringSelf if type(object) == "string" then return object else local _, count = gsub(ObjectDescription(object),"%(","") if count>1 then return strsub(ObjectDescription(object), strfind(ObjectDescription(object),"(",1,true)+1,strfind(ObjectDescription(object),")",1,true)-1) else local StrRef = "object" .. random(9999999) ExecuteAction("SET_UNIT_REFERENCE", StrRef, object) return StrRef end end end
  15. The idea to "replace" the news ticker options is actually not too bad: BTW: My new "more fps method" does't speed up the visual game speed anymore.