Jump to content

Mjjstral

Members
  • Content count

    100
  • Joined

  • Last visited

Community Reputation

20 Excellent

About Mjjstral

  • Rank
    Specialist

Contact Methods

Profile Information

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

Command & Conquer Profile

  • Favourite C&C
    Kanes Wrath

Recent Profile Visitors

1,142 profile views
  1. This should fix it. It's now more error robust in general: IronCurtain = {} IronCurtain["Targets"] = {} IronCurtain["BuildingRef"] = {} IronCurtain["Ready"] = {} function OnIronCurtainBuildingCreated(self) IronCurtain["BuildingRef"][ObjectTeamName(self)] = self if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end IronCurtain["Ready"][ObjectTeamName(self)] = false end function OnIronCurtainBuildingDestroyed(self) IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil IronCurtain["Ready"][ObjectTeamName(self)] = false end function OnIronCurtainReady(self) IronCurtain["Ready"][ObjectTeamName(self)] = true if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end if IronCurtain["Targets"][ObjectTeamName(self)] and getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and not ObjectTestModelCondition(self,"UNDERPOWERED") then --ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"IronCurtainWeapon") ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPower_IronCurtain",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1])) IronCurtain["Ready"][ObjectTeamName(self)] = false end end function OnHarvesterHealth25Percent(self) if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self) if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then --ObjectCreateAndFireTempWeapon(self,"IronCurtainWeapon") ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPower_IronCurtain",GetObj.String(self)) IronCurtain["Ready"][ObjectTeamName(self)] = false end end function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self) local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self) if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end end function GetIndexOfTableElement(table,element) if not table then return nil end for i=1,getn(table),1 do if table[i]==element then return i end end end Hm I'm also on win7... Shouldn't be system dependent acually. Why does the lua code pasted in these forum text boxes appear so whitish and unreadable ?
  2. I'm currently trying to create a prototype of a logic circuits mod for Kane's Wrath. You will basically have different elements you can connect via cables. One Example: A "switch" and an "enemy detector" connected via an AND gate and the output cable leads to an "sound alarm" element. Functionally it will look like in games like Minecraft (redstone logic) or Starmade, see here: Now my problem: I need to connect the elements somehow via cables creating a hook up, latch or click in effect that somehow (likewise via modelcondition) triggers a lua event. I will handle the whole logic in lua then. Let's brainstorm ! Also what parts do you think should be added ? (so far on my list: lua computer terminal (like in ComputerCraft, each computer with own lua file), Gates, Structure Status Detector, AND, OR, NOT, switch, toggle switch, sound alarm, structure enabler/disabler, structure command giver (build commands...), unit command giver, laser trigger, team command giver, unit counter, seller, repairer, light (with rgb code connectors), text displayer) If someone wants to help me especially with the model creation and also xml coding wise (beside this forum), feel free to contact me (also consider joining the SAGE modding discord).
  3. And here is an alternative I made earlier but you can disregard. It uses lua script timers (meta mod) and gets the harvester refs automatically. So it's a more lua self contained solution. IronCurtainBuildingList = {} function IronCurtainBuildingOnCreated(self) tinsert(IronCurtainBuildingList,self) SetScriptTimer(1,IronCurtainAttackManagement) end function IronCurtainBuildingOnDestroyed(self) local Index = GetIndexOfTableElement(IronCurtainBuildingList,self) if Index then tremove(IronCurtainBuildingList, Index) end DeleteScriptTimerAction(IronCurtainAttackManagement) end function IronCurtainBuildingOnPowerOutage(self) local Index = GetIndexOfTableElement(IronCurtainBuildingList,self) if Index then tremove(IronCurtainBuildingList, Index) end DeleteScriptTimerAction(IronCurtainAttackManagement) end function IronCurtainBuildingOnPowerRestore(self) tinsert(IronCurtainBuildingList,self) SetScriptTimer(1,IronCurtainAttackManagement) end IronCurtainSchedule = {} function IronCurtainAttackManagement() local IronCurtainObjectWhiteList = GetObjectTypeListForTeam(team,AddToObjectTypeList("HarvesterTypeList","GDIHarvester","NODHarvester","ALIENHarvester")) for i=1,getn(IronCurtainBuildingList),1 do if IronCurtainSchedule[IronCurtainBuildingList[i]] == 0 and not ObjectTestModelCondition(GetObj.Table(IronCurtainBuildingList[i]),"UNDERPOWERED") then for j=1,getn(IronCurtainObjectWhiteList),1 do if GetHealth(IronCurtainObjectWhiteList[j].ref) <= 25 then ObjectCreateAndFireTempWeapon(IronCurtainObjectWhiteList[j].ref,"IronCurtainWeapon") --ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY_ON_NAMED", IronCurtainBuildingList[i], "Command_IronCurtainWeapon", IronCurtainObjectWhiteList[j].ref) end end else IronCurtainSchedule[IronCurtainBuildingList[i]] = IronCurtainSchedule[IronCurtainBuildingList[i]] - 1 end end end function GetObjectTypeListForTeam(team,ObjectType) --ObjectType or ObjectTypeList local RefList = {} local ObjRef = "" local y = 1 local TempObjectRefTable={} ExecuteAction("SET_IGNORE_SKIRMISH_VICTORY_CONDITIONS", 1) repeat ObjRef=RandomString(5) ExecuteAction("TEAM_SET_PLAYERS_NEAREST_UNIT_OF_TYPE_TO_REFERENCE",ObjectType,team,ObjRef) if EvaluateCondition("NAMED_NOT_DESTROYED",ObjRef) then RefList[y]={} RefList[y]["ref"]=ObjRef RefList[y]["team"]=team RefList[y]["type"]=ObjectType RefList[y]["powered"]=1 tinsert(TempObjectRefTable,ObjRef) ExecuteAction("UNIT_SET_TEAM",ObjRef,"team") y=y+1 else break end until(not EvaluateCondition("NAMED_NOT_DESTROYED",ObjRef)) for j=1,getn(TempObjectRefTable),1 do ExecuteAction("UNIT_SET_TEAM",TempObjectRefTable[j],team) end ExecuteAction("SET_IGNORE_SKIRMISH_VICTORY_CONDITIONS", 0) return RefList end function AddToObjectTypeList(ObjectTypeList,...) for i=1,getn(arg),1 do ExecuteAction("OBJECTLIST_ADDOBJECTTYPE", ObjectTypeList, arg[i]) end return ObjectTypeList end function GetHealth(input,HealthType) local HealthCompareType = "" if HealthType == nil or HealthType == "unit" or HealthType == 1 then HealthCompareType = "UNIT_HEALTH" else HealthCompareType = "EVAL_TEAM_HEALTH" end for i=1,101,1 do if EvaluateCondition(HealthCompareType, input, CompareTable["<"], i) then return i-1 end end return 0 end function GetIndexOfTableElement(table,element) for i=1,getn(table),1 do if table[i]==element then return i end 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) --v end end return object end end
  4. My solution assumes that a player will only have 1 iron curtain building at the same time (code adaption for more than 1 possible). 1. Make it a special power that triggers a weapon and then an attribute modifier. Use Ravendarks idea to trigger a SPECIALPOWER1_READY lua event that calls the function OnIronCurtainReady. 2. In additon for the harvesters use these events to trigger the functions OnHarvesterHealth25Percent and OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead. <ModelConditionEvent Name="HEALTH_PERCENT_25"> <Conditions>+HEALTH_PERCENT_25</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="HEALTH_PERCENT_25_NOT"> <Conditions>-HEALTH_PERCENT_25</Conditions> </ModelConditionEvent> 3. Now the lua code: IronCurtain = {} IronCurtain["Targets"] = {} IronCurtain["BuildingRef"] = {} IronCurtain["Ready"] = {} function OnIronCurtainBuildingCreated(self) IronCurtain["BuildingRef"][ObjectTeamName(self)] = self IronCurtain["Targets"][ObjectTeamName(self)] = {} IronCurtain["Ready"][ObjectTeamName(self)] = false end function OnIronCurtainBuildingDestroyed(self) IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil IronCurtain["Ready"][ObjectTeamName(self)] = false end function OnIronCurtainReady(self) IronCurtain["Ready"][ObjectTeamName(self)] = true if getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then --ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"IronCurtainWeapon") ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPower_IronCurtain",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1])) IronCurtain["Ready"][ObjectTeamName(self)] = false end end function OnHarvesterHealth25Percent(self) tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self) if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then --ObjectCreateAndFireTempWeapon(self,"IronCurtainWeapon") ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPower_IronCurtain",GetObj.String(self)) IronCurtain["Ready"][ObjectTeamName(self)] = false end end function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self) local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self) if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end end function GetIndexOfTableElement(table,element) for i=1,getn(table),1 do if table[i]==element then return i end end end So you need in total 5 lua events (3 for the structure and 2 for the harvesters). 4. optionaly if you want to always attack the harbester with the lowest health from the pool of all harvesters that have health < 25: function GetMinHealthUnit(UnitTable) if getn(UnitTable) == 0 then return nil end local MinHealthUnitRef = UnitTable[1] local MinHealth = GetHealth(UnitTable[1]) for i=2,getn(UnitTable),1 do if GetHealth(UnitTable[i]) < MinHealth then MinHealthUnitRef = UnitTable[i] end end return MinHealthUnitRef end function GetHealth(Unit) local UnitRef = GetObj.String(Unit) for i=1,101,1 do if EvaluateCondition("UNIT_HEALTH", UnitRef, CompareTable["<"], i) then return i-1 end end return 0 end So replace GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]) with GetObj.String(GetMinHealthUnit(IronCurtain["Targets"][ObjectTeamName(self)]))
  5. I found the error: "NAMED_EXIT_ALL" gives a command to the transporter to thorw out it's inmates. So becomes much more simple: function OnSovietHalfTrackReallyDamaged(self) --add the lua event to scriptevents.xml too ExecuteAction("NAMED_EXIT_ALL",self) if PassengerTable[tostring(self)] == nil then return end for i=1,getn(PassengerTable[tostring(self)]),1 do ExecuteAction("UNIT_AI_TRANSFER",PassengerTable[tostring(self)][i],1) --enable ai in case it was disabled end PassengerTable[tostring(self)]=nil end If you want to give the exit commands to the inmates one by one you can use this: function OnSovietHalfTrackReallyDamaged(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_BUILDING",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 So to sum up: "NAMED_EXIT_ALL" = command for object harboring units, "NAMED_EXIT_BUILDING" = command for units within transporters (or buildings).
  6. I totally love procedural algortihms and after genuine games like No Man's Sky (proc planets, proc animals, proc plants, proc missions, proc ships, proc all xD) I was always thinking about how to use proc gen in the sage engine. Here is one idea I came up with: Procedural lua mission+story gamemode, playable on any map (map independent): 1. Mission Templates: These are the puzzle pieces that get merged together to create a mission. I expect 20-30 unique templates with additional subvariants. Non-trivial interlockings between templates with good overall coherence. 2. Random Map Events: These are events that happen randomly during the course of the mission and give an additional variance for gameplay. Examples: Random positional asteroid storm, random black holes appear on map, third party units appear and cause trouble (creepsteam),... (events like these are already implemented in aod gamemode of meta mod) 3. Map Regeneration (optional) flexibiity: We can remove all objects on the map (even tiberium fields) and set up an entirely new object/building placement configuration. Im also thinking about random maze structures and stuff like that for maximum variance and unpredictability. 4. Seed based: For procedural lua missions I thought about a wide range of mission templates that all get put together by a random seed value. The user can also use his own custom seed values. Example: MissionTemplate1 -> defend a building (seed code "DB1" - number stands for number of builidngs to defend), MissionTemplate2 -> Capture one ore more Buildings ("CB3" - number stands for number of buildings to capture), MissionTemplate3 -> guard a unit to reach a specific point on the map ("GU1" - numnber stands for number of units to guard so that they savely reach the destination"). In this case we could have a seed like "DB1CB3GU1". In addtion we could introduce another number that provides the schedule. Example addtional 1 to DB1 tells that it is the first mission objective hence DB11, so in the end we can have mission objectives run simultanously. The seed complexity could become astronomically more complex also if we add story line parts. Eventually share your seeds online and create your own missions stories by hand. Mission+Story Editor/Creator thinkable. 5. Infinite mode: Play very looong games like in age of empires with new missions continueing after each mission again and again. Adaptive difficulty could also be used. Will need a lua based savegame as due to the complexity of map and scipt manipulation standard savegames will crash the game. 6. Procedural story line (optional): A huge number of text, video, cinematic camera movement scripts and sound fragments put together for an unpredictable story with missions each time. Something I won't ever do on my own. 7. Online coop functionality. 8. Self evolutionary AI procedural mission/story director (never seen that in any videogame ever). Closest is the AI director in Left for Death 2 or FEAR but doesn't have proc contect. I'm not saying I will ever make all of this or any of this but maybe a barebone version someday. It's all technically possible and without real live I would do it. This is an inspirational post on new things we can still do to push the limits for SAGE modding. Please share your ideas on what else could be added to this idea complex and what you think about all this. Possibilities are endless.
  7. Yes it's possible in many variants I can think of (mostly lua heavy solutions): 1. Variant - AI Co-Control: This let's an hard ai co control the human players faction side by side. Change MakeAllSkirmishSidesAIControlled = No to Yes in skirmishaidata.ini. You can also make it toggleable e.g. via a playerpower button and with help of lua so that the ai only becomes active if the player wishes to. That's something I had running in the past and it worked great but not for custom factions unfortunately (crashes) that's why I needed to disable it in MetaMod. You could also make an ability to select certain buildings/units during game that the ai then won't control anymore if you wish (via lua) 2. Variant - One basebuilder and one Unit controller: Units get transfered immediately to the other player on creation via lua. A "victory condition dummy" and custom victory condition lua scipts ensure correct win/lose conditions as one player doesn't own any buildings. The sides can even be made switchable and if both players are humans you can even implement an accept/deny button. 3. Variant - see MetaMod diplomacy options menu: "temporary switch sides", "temporary give control to another player", "temporary take control of another player" (with accept/deny button in case of human player). All these options are toggleable. New units created will still belong to the player who created them but that could also be changed if needed. 4. Variant - not recommended: A lua co routine checks every x ms if a player has selected a unit or building of the allied player. If so the unit gets immidiately transfered and tranfereed back after unselect so that it's not noticeable. Downside: Short selection keys (q,w...) need to be replaced by an additonal selection menu. But these menu entries can have keys assigned themselves. Group assignment won't work here except if you also make menu entries that trigger lua selection scripts for that. 5. Everything inbetween - mixture of thes variants. Just as an interesting sidennote: We can use 4 more players/teams that are always available regardless of the playercount: Lua Team Names: NeutralTeam="/team" CivilianTeam="PlyrCivilian/teamPlyrCivilian" CreepsTeam="PlyrCreeps/teamPlyrCreeps" ObserverTeam="ReplayObserver/teamReplayObserver" I use the CreepsTeam (always enemy to all) e.g. for my art of defense gamemodes, so we don't need another dummy ai player. CivilianTeam,NeutralTeam or ObserverTeam could be used as an artificiall ally. You could totally program an independent lua ai for these to support the player too. But it's a loooot of work.
  8. Regarding the lua command: The last parameter (percentage of horde) is missing: ExecuteAction("UNIT_SET_MODELCONDITION_FOR_DURATION", self, "USER_17", "4", "100") And for numbers it doesn't matter if you use quotation marked numbers or pure numbers. It gets converted to double values on the c side of the lua c api nontheless.
  9. I invite all of you to the new SAGE Engine Modding discord server with seperate channels for each game. Basically for every good modding community nowadays there is a discord server so I had to create one. Invite all SAGE modders you know so that we can quickly grow. Thank's !!! I still need at least 2 more moderators so just contact me for that if you like to do it https://discord.gg/TfdcQTn
  10. You could make a simple batch script with/and/or use of some regex replacements.
  11. Of course we can have a very reliable three-sigma-rule heuristic (99.7%) based set of numbers if we wish. And for my argumentation a lower conservative estimation would always be valid. Let's not spam this forum with this, better write pm's if you need further explanations
  12. See Bayes' theorem Misunderstanding from your side. Every map script of course affects the ram. By saying it this way I just wanted to point out that it is not a permanent file related change or something. The thing is this exploit is so damn simple. You just need to activate the camera letterbox mode and exit the map, done... I'm not sure but maybe this even works if you exit the map during campaign camera letterbox mode parts. Then you don't even need this map. Also there are many custom maps played in mp (td,aod maps especiallly) with cinematic like intros, just exit the game during that phase and boom you also have that same exploit enabled. Enter another mp game after that and unintentionally zoom out more...
  13. See the relation between SteamDBCurrentPlayer and CnCOnlineCurrentPlayers. Reliable ? Not sure but at least we can assume that most players use singleplayer (it has always been in rts games like that, a rts game dev once told me). Don't nail me on statements like that. It's clear that this is a really rough guess and people can make their own opinion (but I'm almost sure more people use the origin+retail then steam version). Sorry it was not in any way my intention to offend you in any way ! Yes but that doesn't matter because the steamdb current player number which I used for my rough guess also coreelates to the same peak times. For singleplayer players as I stated. I myself could't play the BFME games (in sp of course) without more zoom out. Also for CNC4 it is really great to have such an amazingly better overview. You should test it, it's a complete game changer to the good. And as you see this map exploit also supports RA3 uprising which is as you know a pure singleplayer game. I'm sorry that I caused so much trouble. I was never into all that multiplayer stuff but now I see the point and the problems for that regarding the strict fair play rules. Still in my opinion more people benefit from it then not. This map has been a part of metamod already quite some time, I just thought to bring it to the people as a seperate thing.
  14. I mean there are at least 15 sp players for each mp player. That makes my argument even more valid because then there are maybe even 30 sp players for each mp player (you can actually see the number of cnc-online players here, hence my deduction). So if we deal with this in a philanthropic way and use utilitarianism logic, this exploit should be public for the benefit of the majority of players.
  15. 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.
×