Purrfekshawn Posted December 25, 2020 Posted December 25, 2020 (edited) Horrible Game Breaking Design Flaw - Protector Bots first shields Everything and only then Caster - reason found! The reason of this has been found, and since that requesting IMMEDIATE fix (as We're always Nice n.n, so Fix it #RITENOW!!! Protector Bots first shields literally EVERYTHING - Other Bots, Seeker Drones, Acid Mortars, Incarnate Pets, the Demon, the Devil (also the whole list down)..., gracefully ignoring the only thing - its owner. It has been known for so long time, and now l looked in Dev files and found the actual reason of this Atrocious, Horrendous, Horrid code error: It's located in "%CoHDevSourceFilesFolder%\coh-server-original-master\MapServer\ai\entaiCritterActivityCombat.c" 1835 Entity* aiCritterFindTeammateInNeed(Entity* e, AIVars *ai, F32 range, AIPowerInfo* info, int targetType) 1836 { 1837 Entity* weakest=NULL, *myowner; 1838 F32 dHP; 1839 F32 weakestdHP=0; 1840 F32 rangeSQR = range*range; 1841 F32 distSQR; 1842 1843 // myowner only allows owner as target. This section tries to buff teammates 1844 // the following section, targets the owner. it is after so that it can replace the teammates 1845 if(ai->teamMemberInfo.team && (targetType != kTargetType_MyOwner) && (targetType != kTargetType_MyCreator)){ 1846 AITeamMemberInfo* member; 1847 S32 isTitan = ai->brain.type == AI_BRAIN_MALTA_HERCULES_TITAN; 1848 1849 for(member = ai->teamMemberInfo.team->members.list; member; member = member->next){ 1850 // valid ents to buff are entities that aren't self and alive. 1851 // targettype_mypet requires that the ent is a pet 1852 Entity *entMember = member->entity; 1853 int isValidEnt = (entMember != e) && (entMember->pchar->attrCur.fHitPoints > 0); 1854 if (targetType == kTargetType_MyPet) 1855 { 1856 isValidEnt &= (entMember->erOwner == erGetRef(e)); 1857 } 1858 else if (targetType == kTargetType_MyCreation) 1859 { 1860 isValidEnt &= (entMember->erCreator == erGetRef(e)); 1861 } 1862 if(isValidEnt){ 1863 AttribMod *pmod; 1864 AttribModListIter iter; 1865 bool bActive=false; 1866 const BasePower *ppowBase = info ? info->power->ppowBase : NULL; 1867 1868 if(isTitan){ 1869 AIVars* aiMember = ENTAI(entMember); 1870 1871 if(aiMember->brain.type != AI_BRAIN_MALTA_HERCULES_TITAN){ 1872 continue; 1873 } 1874 } 1875 1876 if(info) 1877 { 1878 if(!aiPowerTargetAllowed(e, info, entMember, true)) 1879 continue; 1880 } 1881 1882 1883 if(info && !(info->groupFlags & AI_POWERGROUP_HEAL_ALLY)) 1884 { 1885 EntityRef myRef = erGetRef(e); 1886 pmod = modlist_GetFirstMod(&iter, &entMember->pchar->listMod); 1887 while(pmod!=NULL){ 1888 if(pmod->ptemplate->ppowBase==ppowBase && pmod->erSource == myRef){ 1889 bActive=true; 1890 break; 1891 } 1892 pmod = modlist_GetNextMod(&iter); 1893 } 1894 } 1895 1896 if(bActive) 1897 continue; 1898 1899 distSQR = distance3Squared(ENTPOS(e), ENTPOS(entMember)); 1900 if (distSQR <= rangeSQR) { 1901 dHP = entMember->pchar->attrMax.fHitPoints - entMember->pchar->attrCur.fHitPoints; 1902 // Prefer weak members, otherwise prefer those in melee, 1/X chance of just skipping a guy, so that not everyone heals/buffs the same guy 1903 if (!weakest || rand()%3 && (dHP > weakestdHP || (dHP == weakestdHP && ABS_TIME_SINCE(ENTAI(member->entity)->time.wasAttacked) < SEC_TO_ABS(5)))) { 1904 weakest = entMember; 1905 weakestdHP = dHP; 1906 } 1907 } 1908 } 1909 } 1910 } 1911 if ((targetType != kTargetType_MyPet) && (targetType != kTargetType_MyCreation)) 1912 { 1913 EntityRef owner = targetType == kTargetType_MyCreator ? e->erCreator : e->erOwner; 1914 if(owner && (myowner = erGetEnt(owner))) 1915 { 1916 AttribMod *pmod; 1917 AttribModListIter iter; 1918 bool bActive=false; 1919 const BasePower *ppowBase = info ? info->power->ppowBase : NULL; 1920 1921 if(info && !(info->groupFlags & AI_POWERGROUP_HEAL_ALLY)) 1922 { 1923 pmod = modlist_GetFirstMod(&iter, &myowner->pchar->listMod); 1924 while(pmod!=NULL){ 1925 if(pmod->ptemplate->ppowBase==ppowBase){ 1926 bActive=true; 1927 break; 1928 } 1929 pmod = modlist_GetNextMod(&iter); 1930 } 1931 } 1932 1933 distSQR = distance3Squared(ENTPOS(e), ENTPOS(myowner)); 1934 if (!bActive && distSQR <= rangeSQR) { 1935 dHP = myowner->pchar->attrMax.fHitPoints - myowner->pchar->attrCur.fHitPoints; 1936 // Prefer weak members, otherwise prefer those in melee, 1/X chance of just skipping a guy, so that not everyone heals/buffs the same guy 1937 if (!weakest || rand()%3 && (dHP > weakestdHP || (dHP == weakestdHP && ABS_TIME_SINCE(ENTAI(myowner)->time.wasAttacked) < SEC_TO_ABS(5)))) { 1938 weakest = myowner; 1939 weakestdHP = dHP; 1940 } 1941 } 1942 } 1943 } 1944 return weakest; 1945 } This function consists of 2 main subroutines - one starts at #1845 and ends at #1910 and another starts at #1911 and ends at #1943. First of them searches all targets those need the buff except for the Owner, and another one looks at the Owner. Problem is - the value "weakest" will likely be non-zero at the moment it gets to the second subroutine, and as it's coded now it won't be overwritten thus it results that Owner gets support from the pets from the LAST order, when it should be receiving buff in the FIRST order, otherwise the robots are a junk that worth only recycling. Thea'z "positronic matrix" salvage in game, so robots shud obey laws of robotics, first of which is NOT TO LET THEIR CREATOR BE HURT (2nd is obey the Creator), and only 3rd of which is NOT TO LET THEMSELVES BE HURT. Yet robots those're in game put the 3rd law above the 1st, which's total blastheadness in its crystallic solid form. Interesting to note that according to how it's coded if your character has LOW HP, the robot may prefer shield the character over other pets, you can test it on live, do major injury to yourself, then summon protector bots, they may shield you first at that case. In order to fix it Devs need to swap these subroutine places. In my experimenting on private server it did the trick. Also it's possible to make even stronger assumption, for instance if do this: 1937 if (!weakest || rand()%3 && (dHP > weakestdHP || (dHP == weakestdHP && ABS_TIME_SINCE(ENTAI(myowner)->time.wasAttacked) < SEC_TO_ABS(5)))) { replace to 1937 if (!weakest || (dHP > weakestdHP) || (dHP == weakestdHP) ) { (it's what l have on private server) then the need of buffing the Owner will be stronger, and the other members will be buffed only when they have Higher HP delta (maxHP-currentHP) than the owner (or special effect is unable to be cast onto owner, bots for instance have NOT lost ability to cast shield on other robot after this replacement FYI). If completely skip the string: 1937 if ( true ) { Then the Owner will be buffed/healed even when he (or Nice Beautiful She, or Our Imperial Majesty) has 70% of maximum HP, when there might be teammates with 10 HP and they won't receive the buff/heal that would otherwise save their lives. So it's double edged sword... But what is clear is that it IS a bug that bots cast FF on Owner in the last order, and it IS to be fixed, and it IS to be fixed this instant. It's the Merry Christmas, so letz be nice & fix it now!!! 😊 Edited December 25, 2020 by Purrfekshawn To keep this game safe, We have to give it to the world. Arc ID #13097 - Archvillain Beatdown, try it out! Arc ID #21066 - Archvillain Beatdown - Past Edition! Letz now talk about existing Incarnate Lore Pets: https://forums.homecomingservers.com/topic/50351-incarnate-lore-pets-look-through-fix-and-improve/
Wavicle Posted December 25, 2020 Posted December 25, 2020 well your "MUST be fixed INSTANTLY" isn't really a good approach, but your detail on the code is fantastic! 1 Wavicle's Guide To What Really Matters: What Needs To Be Done On Every Toon
EmperorSteele Posted December 25, 2020 Posted December 25, 2020 Can't you just summon your protector bot first, wait until he bubbles you, and THEN summon everything else?
Wavicle Posted December 26, 2020 Posted December 26, 2020 3 hours ago, EmperorSteele said: Can't you just summon your protector bot first, wait until he bubbles you, and THEN summon everything else? That won't solve the problem, it needs to be able to reapply the bubbles during missions. 1 Wavicle's Guide To What Really Matters: What Needs To Be Done On Every Toon
Retired Game Master GM Tock Posted December 26, 2020 Retired Game Master Posted December 26, 2020 (edited) This is directed at the Original Post, but something for all users to know. Server programming is past the scope of this whole forum. Key distinction, that: Not just bug reports, the entire forum itself. We are interested in hearing bug reporting from a player perspective. And the majority of readers in these forums are not programmers. Including yours truly, I'm nobody special. I put myself in that grouping as well. Put simply and respectfully, there is no frame of reference for players to discuss this past your own perspective. All I can tell you-- if there is a call for a programmer, specialist, or other technical work to be made, there will be an APB made in the Developers Corner area. Edited December 26, 2020 by GM Tahquitz
Recommended Posts