Jump to content

Mjjstral

Members
  • Content count

    110
  • Joined

  • Last visited

Everything posted by Mjjstral

  1. Well my intentionts with this were entirely good. There are clearly more singleplayer players that benefit from this then multiplayer players using it as an advantage especially for the BFME games (utilitarianism). If we look at steamdb and cnc-online we can guess a ration for sp:mp of 1:15. And for the multiplayer part the thing is that you can easily detect if someone uses it with help of the replay (from the "eyes of player mode"). So in the end this is actually a good filter to detect all "dishonest" people and let them get banned if necessary. So as all things in live this exploit has it's polarity. Nuclear fission for instance can be used for good to produce power or for bad to produce weapons. But is that a reason to completely ban the knowledge of nuclear fission ? I unintentionally found other even undetectable and by far more heavy exploits that work in multiplayer too but these I will never make public because the singleplayer benefit is just to slim.
  2. I posted it 7 times (for each game this thing works) because I consider this to be quite a beneficial game changer that every player should make use of. Sage engine games and their max zoom out have always been a problem in my eyes. For C&C Generals we could fix the zoom easily in the gamedata.ini. But that didn't work for most games after Generals. Now we have an easy modless solution that even works for multiplayer. It's a huge coincidence that I even found this bug, unfortunately 10 years too late for most former players lol.
  3. You can spawn the monetary compensation dummy object quite hidden in the down-left corner so players won't notice. It's a lua oneliner if you have the GetTeamName function: ExecuteAction("CREATE_OBJECT","MoneyDummy",GetTeamName(self),"0.00,0.00,0.00",0)
  4. It's ridiculous, they removed my posts about this from the gamereplays forums. Do people really consider this exploit to be an unfair advantage ? It's just a map....
  5. Ok I've added Lord of the Rings The Battle for Middle-earth 1 as well as Command and Conquer Red Alert 3 Uprising. Unfortunately it doesn't work for vanilla red alert 3, sorry.
  6. I have some origin keys left. PM me if you want one: Sim City 2000 Special Edition (4 keys) Battlefield 3 Limited Dead Space Dragon Age Origins Zumas Revenge This guy also gives away some free keys for origin and steam although most keys are gone already.
  7. The advantage of this exploit is the modlessness and therefore multiplayer compatibility. This exact exploit is only possible via loading a map once. Via mod I came up with similiar solutions to have better zoom (3 different ways in meta mod) but all these always require user input either via player power button or via adjusting the autoconfig file. Your're right I didn't test it for BFME 1. I need to install it first.
  8. 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).
  9. 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.
  10. 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).
  11. 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...
  12. 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.
  13. 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
  14. 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.
  15. 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").
  16. 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
  17. 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
  18. 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!
  19. 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.
  20. 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.
  21. MetaModGuide-SageLuaModdingGuide Meta Mod for C&C Kane's Wrath - ModDB Page + Download of Meta Mod 2 + Source Code + Sage LUA mod SDK *NEW* Meta Mod Tiberium Wars Edition (See readme or moddb description for current limitations) Important new features (small selection, see link above for a more complete list): Meta Credit Shop with rank and xp system, lua based savegames introduced. Autostart config to configure your game very individually with over hundred options. 4 new gamemodes: native art of defense/ tower defense (with advanced evolutionary self learning AI), random army gamemode, unit vs. unit, hero general. diplomacy system: You can even switch teams and give commands to other teams if you apply as a team commander. meta command & meta control menus: Hundreds of options to manipulate the game and use internal script and engine mechanisms. First and third person mode: Completely new game experience. Switch to first person mode during game and leave it whenever you want. Mod script loader system: Easy to use framework to use external lua mod scripts. And much more with over 10,000 lines of lua code Note: Everything in this mod can be disabled one by one if you would like to. So this is now very interesting for all modders out there and I'm very curious about what people will make out of it, as I spend quite some efforts to create the documentation, all these lists and ressources, beside hundreds of lines of lua code which I didnt even use in Meta Mod only to give people the ability to use them later for their projects. Now we are able to let the sage engine pass my definition of the turing test for video games modding, which for me is a timetravel ability (see Meta Credit Shop). I encourage people now to create unique mod scripts for the Meta Mod script loader framework or even create entirely new mods based on my code. The sky is the limit: Create completely new gamemodes and game mechanics! I really hope you like it.
  22. 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
  23. 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.
  24. No this isn't possible at all via LUA alone, because the whole lua environment first get loaded during map load screen. It only works like that: After the map load on game start, lua can test what options were enabled and then do it's stuff dependent on this. So the only workarounds to have new skirmish setup options without sacrificing the crate option are: 1. Trivial: Let lua always enable the random crate option and let the skirmish option be useable for other options. 2. The host of the game gets asked immediately after map load to decide about certain options. This then works via player power buttons (accept/deny). For some confirmations this is already used in meta mod and will also get used for player live pools in possibly future updates. During host ingame option setup the game can be set to a frozen state. 3. Use a specially made dummy faction that immediately enables the requested option and then removes itself on game start. The name of the faction is then of course the name of the option. You can even go farther and let every handycap percentage step for that faction be a seperate sub option. 4. Use a config file to enable/disable options + (optionally:) also let the user toggle these options via an ingame text menu. This is the way meta mod also handles this. Thanks to this method the user can toggle over 100 options via config file in meta mod. 5. Stranger solutions: Use any other option like a special money step. This can work because lua can read the Skirmish.ini file (and all other files) in your appdata/.../profiles/user folder and detect each and every option you used. You could also use the voip option box and even special hotkey assignments to toggle options. There are potentially sacrificable options like the ticker options: ShowTickerAds, ShowTickerNews or ToolTipDelay in the Options.ini, just to mention a few. Keep in mind only the first three solutions can be multiplayer compatible. I can go more into detail for certain aspects if you wish.
  25. Some quick untested additons: PassengerTable={} 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 function SovietConscriptEnterTransport(self,other) -- ExecuteAction("NAMED_STOP",self) if PassengerTable[tostring(self)] == nil then PassengerTable[tostring(self)]={} end tinsert(PassengerTable[tostring(self)],other) ExecuteAction("UNIT_AI_TRANSFER",self,0) --stop ai interference (optional) ExecuteAction("NAMED_ENTER_NAMED", self, other) ExecuteAction("SHOW_MILITARY_CAPTION", "GETTING_IN_TRANSPORT", 5) end function OnSovietHalfTrackEmpty(self) if GetHealth(self) > 25 then --and not EvaluateCondition("UNIT_HAS_PASSENGER",GetObj.String(self)) --optional ObjectBroadcastEventToAllies(self, "TransportIsEmpty", 200) ExecuteAction("SHOW_MILITARY_CAPTION", "HALFTRACK_EMPTY", 5) end end CompareTable = { LT=0, LE=1, EQ=2, GE=3, GT=4, NE=5, ["<"]=0, ["<="]=1, ["=="]=2, [">="]=3, [">"]=4, ["~="]=5 } function GetHealth(object) object=GetObj.String(object) for i=1,101,1 do if EvaluateCondition("UNIT_HEALTH",object,CompareTable["<"],i) then return i-1 end end return 0 end
×