Author Topic: Legit Checker Script  (Read 938 times)

Legacy_Birdman076

  • Sr. Member
  • ****
  • Posts: 320
  • Karma: +0/-0
Legit Checker Script
« on: January 13, 2011, 09:32:37 pm »


               Does any have or know of a good all encompassing onEnter legit checker script which will boot and log (so they can be added to the ban list) uber players who log in to the server will max stats and hacked gear? Is it even necessary anymore?
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Legit Checker Script
« Reply #1 on: January 13, 2011, 11:46:00 pm »


               Yes, it's still necessary. My preference is not to boot, but to send to an isolated area, to explain to the player what is happening, in case the issue is caused by their use of another module's or server's files. What OS is your server on, and are you using nwnx?



Funky
               
               

               
            

Legacy_420

  • Sr. Member
  • ****
  • Posts: 370
  • Karma: +0/-0
Legit Checker Script
« Reply #2 on: January 14, 2011, 01:14:29 am »


               I find that enabling Enforce Legal Characters and Item Level Restriction takes care of most of the riffraff. Other than that I check for and remove "bad strref" item properties and set the PC's immortal and plot flags to false.

I've DMed on a server that checked for more specific things like number of attribute points, skill points, and feats, but I never found that necessary on the server I host.

-420
               
               

               


                     Modifié par 420, 14 janvier 2011 - 01:14 .
                     
                  


            

Legacy_Birdman076

  • Sr. Member
  • ****
  • Posts: 320
  • Karma: +0/-0
Legit Checker Script
« Reply #3 on: January 14, 2011, 02:15:35 am »


               Win XP Pro for the server, and yes I am using nwnx. As far as enforce legal and item level I can't because the server uses Shayan's sub race system with skins. Isolated area would be a better approach if the people doing it are not predominantly riff raff like the case was a few years back.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Legit Checker Script
« Reply #4 on: January 14, 2011, 03:06:48 am »


               I'm reformatting the code we use. It was posted on a forum that eats indents. Will have it up shortly.



Funky
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Legit Checker Script
« Reply #5 on: January 14, 2011, 04:15:28 am »


               Everything following this sentence is a repost from one of my old weathersong posts, reformatted and updated where I noticed anachronisms.
///////////////////////////////////////////////////////


I'll happily share my anti-cheat code, though without a demo mod its a bit convoluted at best, and it requires includes from my legendary level system. On the upside, it is by far the most exacting cheat checker I've seen - it verifies every single feat, rather than counting them, using wrappers from the LL scripts to see if they meet the reqs for each feat. Another, even more secure option, would be the PRC's convo CC, which recreates the character serverside via a convo. That was overkill as far as I was concerned, however, since the best they can slip by mine is not much - just not enough incentive for most. Anyway, these scripts are placed in the Actions Takens lines of a convo that characters must complete in the starting area in order to get jumped to the module proper. Here is a link to the dlg file via dropbox, for reference when reading this.
In the first node (OWNER's) (script is fky_hakchk_start in demo conv):


#include "hgll_func_inc"
void main() {
    object oPC = GetPCSpeaker();
    struct xAbility ability;
    struct xAbility base;
    if (!GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) {//GetXP(oPC) == 0)
        ReplenishLimitedUseFeats(oPC);//in case they try to use the feat to dodge detection (unlikely, but whatever)
        ability = GetRoughAbilities(oPC);//Pull up info on base skills and stats
        base = GetBaseAbilities(ability, oPC);//Process that data further to get base skills and base stats
        SetBaseAbilityMarkers(base, oPC);//Set local ints for the 6 ability scores and 27 skills
        //we will use this data to verify that the characters feats and stats are legal
    }
}


In the next eleven nodes (nodes 2 through 12), I use both OWNER's and PC's nodes to keep the convo shorter (script is fky_hakchk_feat in demo convo):


#include "hgll_func_inc"
int GetIsRacialFeat(int nFeat) {
    if ((nFeat > 226) && (nFeat < 251))
        return TRUE;
    int nReturn = FALSE;
    switch(nFeat) {
        case 256:
        case 258:
        case 354:
        case 375: nReturn = TRUE; break;
        default : nReturn = FALSE; break;
    }
    return nReturn;
}

int GetIsDomainFeat(int nFeat) {
    if ((nFeat > 305) && (nFeat < 326))
        return TRUE;
    return FALSE;
}


void DebugIt(string sIllegal) {
    string sInsert = "Reason for feat failure = ";
    sInsert = sInsert + sIllegal;
    WriteTimestampedLogEntry(sInsert);
    SendMessageToAllDMs(sInsert);
}

int GetIsMiscclassOrRaceFeat(int nFeat, object oPC) {
    if (((nFeat == 1) || (nFeat == 41)) && GetclassByPosition(1, oPC) == class_TYPE_RANGER)
        return TRUE;
    if (((nFeat == 6) || (nFeat == 39)) && GetclassByPosition(1, oPC) == class_TYPE_MONK)
        return TRUE;
    if (nFeat == 170 && GetRacialType(oPC) == RACIAL_TYPE_GNOME)
        return TRUE;
    return FALSE;
}

int GetIsFeatLegal(int nFeat, object oPC, int nclass1) {
    if (GetIsMiscclassOrRaceFeat(nFeat, oPC))
        return TRUE;//covers feats given to classes or races regardless of requisites
    if (GetIsFeatDevCrit(nFeat))
        return FALSE;
    if (!GetAreFeatStatReqsMet(nFeat, oPC)) {DebugIt("StatReq");
        return FALSE;}
    if (!GetAreFeatSkillReqsMet(nFeat, oPC)) {DebugIt("SkillReq");
        return FALSE;}
    if (!GetAreFeatFeatReqsMet(nFeat, oPC)) {DebugIt("FeatReq");
        return FALSE;}
    if (!GetHasRequiredSpellLevelForFeat(oPC, nFeat)) {
        DebugIt("SpellLevReq");
        return FALSE;
    }
    if (!GetIsclassFeat(nFeat, nclass1, oPC) &&
        !GetIsRacialFeat(nFeat) &&
        !GetIsDomainFeat(nFeat) &&
        !GetIsGeneralFeat(nFeat)) {
        DebugIt("Non-class/Gen");
        return FALSE;//if it's not a class feat and it's not a general feat return FALSE
    }
    return TRUE;
}

void main() {
    object oPC = GetPCSpeaker();
    int nclass1 = GetclassByPosition(1, oPC);
    int nTrack = GetLocalInt(oPC, "FeatCheckCount");//we save scripts by using the same one in all the nodes and incrementing this int to switch the feats checked
    int nFeat;
    string sIllegal;
    int nStart = nTrack*100;
    int nBusted = GetLocalInt(oPC, "Hacker");
    if (!GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) {//GetXP(oPC) == 0)
        if (nTrack < 10) {//the feats below 1000

            for(nFeat = nStart; nFeat < (nStart + 99); nFeat++) {//loop through the feat constants (out of 1072)
                if (GetHasFeat(nFeat, oPC)) {//if the PC has the feat
                    if (!GetIsFeatLegal(nFeat, oPC, nclass1)) {
                        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
                        sIllegal = "Illegal Feat ("+ IntToString(nFeat) + ") Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
                        WriteTimestampedLogEntry(sIllegal);
                        SendMessageToAllDMs(sIllegal);
                        break;
                    }
                }
            }
        } else {//feats from 1000 to 1088 - if the character breaks convo and restarts, some feats just checked again

            for(nFeat = 1000; nFeat <= 1088; nFeat++) {//loop through the feat constants (out of 1088)

                if (GetHasFeat(nFeat, oPC)) {//if the PC has the feat
                    if (!GetIsFeatLegal(nFeat, oPC, nclass1)) {
                        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
                        sIllegal = "Illegal Feat ("+ IntToString(nFeat) + ") Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
                        WriteTimestampedLogEntry(sIllegal);
                        SendMessageToAllDMs(sIllegal);
                        break;
                    }
                }
            }
        }
    }
    nTrack++;                                   //increment the tracker so next batch of ints checked next time
    SetLocalInt(oPC, "FeatCheckCount", nTrack); //
}


Thats a loop that checks chunks of 100 feats each time, seperate to prevent TMIs.

In the next node (node 13) (script is fky_hakchk_stat):


#include "hg_inc"

#include "hgll_func_inc"
string GetBicFileName(object oPC) {
    string sChar, sBicName;
    string sPCName = GetStringLowerCase(GetName(oPC));
    int i, iNameLength = GetStringLength(sPCName);

    for(i=0; i < iNameLength; i++) {
        sChar = GetSubString(sPCName, i, 1);
        if (TestStringAgainstPattern("(*a|*n|*w|'|-|_)", sChar)) {
            if (sChar != " ") sBicName += sChar;
        }
    }
    return GetStringLeft(sBicName, 16);
}

int GetLegalHitPoints(object oPC) {
    int nclass = GetclassByPosition(1, oPC);
    int nCon = GetAbilityScore(oPC, ABILITY_CONSTITUTION, TRUE);//GetLocalInt(oPC, "BASE_CON");
    int nclassDie;
    int nFeatBonus = 0;
    int nTotal;
    string sIllegal;
    if(GetHasFeat(FEAT_TOUGHNESS, oPC)) {
        nFeatBonus = 1;
    }
    switch(nclass) {
        case class_TYPE_BARBARIAN:
            nclassDie = 12; break;
        case class_TYPE_PALADIN:
        case class_TYPE_RANGER:
        case class_TYPE_FIGHTER:
            nclassDie = 10; break;
        case class_TYPE_DRUID:
        case class_TYPE_MONK:
        case class_TYPE_CLERIC:
            nclassDie = 8; break;
        case class_TYPE_ROGUE:
        case class_TYPE_BARD:
            nclassDie = 6; break;
        case class_TYPE_SORCERER:
        case class_TYPE_WIZARD:
            nclassDie = 4; break;
        default:
            SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal class
            sIllegal = "Illegal class Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
            WriteTimestampedLogEntry(sIllegal);
            SendMessageToAllDMs(sIllegal);
            break;
    }
    int nRace = 0,nRaceType = GetRacialType(oPC);
    if (nRaceType == RACIAL_TYPE_DWARF ||
        nRaceType == RACIAL_TYPE_DWARF ||
        nRaceType == RACIAL_TYPE_DWARF)
        nRace = 2;
   
    nTotal = nclassDie+nFeatBonus+GetBaseAbilityModifier(nCon)+nRace;
    return nTotal;
}

int GetPointCostOfStat(int nScore) {
    int nCost;
    switch(nScore) {
        case 8: nCost = 0; break;
        case 9: nCost = 1; break;
        case 10: nCost = 2; break;
        case 11: nCost = 3; break;
        case 12: nCost = 4; break;
        case 13: nCost = 5; break;
        case 14: nCost = 6; break;
        case 15: nCost = 8; break;
        case 16: nCost = 10; break;
        case 17: nCost = 13; break;
        case 18: nCost = 16; break;
        default: nCost = 40; break;//any stat other than these indicates illegal edits, so we flag them illegal to start (total over 30 is illegal)
    }
    return nCost;
}

void main() {
    object oPC = GetPCSpeaker();
    if (GetIsObjectValid(GetItemPossessedBy(oPC, "PCList"))) return;//GetXP(oPC) != 0)
    string sIllegal;
    string sName = GetName(oPC);
    string sPlayername = GetPCPlayerName(oPC);
    int nStr = GetLocalInt(oPC, "BASE_STR");
    int nDex = GetLocalInt(oPC, "BASE_DEX");
    int nCon = GetLocalInt(oPC, "BASE_CON");
    int nInt = GetLocalInt(oPC, "BASE_INT");
    int nWis = GetLocalInt(oPC, "BASE_WIS");
    int nCha = GetLocalInt(oPC, "BASE_CHA");
    int nRace = GetRacialType(oPC);
    int nPointTotal;
    switch (nRace) {//neutralize racial bonuses
        case RACIAL_TYPE_DWARF://2con -2cha
        nCon = nCon - 2;
        nCha = nCha +2;
        break;
        case RACIAL_TYPE_ELF://2dex -2con
        nDex = nDex - 2;
        nCon = nCon +2;
        break;
        case RACIAL_TYPE_GNOME://2con -2str
        nCon = nCon - 2;
        nStr = nStr +2;
        break;
        case RACIAL_TYPE_HALFLING://2dex -2str
        nDex = nDex - 2;
        nStr = nStr +2;
        break;
        case RACIAL_TYPE_HALFORC://2str -2int -2cha
        nStr = nStr - 2;
        nInt = nInt +2;
        nCha = nCha +2;
        break;
        case RACIAL_TYPE_HUMAN:
        case RACIAL_TYPE_HALFELF:
        break;
        default:
        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal race
        sIllegal = "Illegal Race Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
        WriteTimestampedLogEntry(sIllegal);
        SendMessageToAllDMs(sIllegal);
        break;
    }
   
    nPointTotal = GetPointCostOfStat(nStr) + GetPointCostOfStat(nDex) + GetPointCostOfStat(nCon) + GetPointCostOfStat(nInt) + GetPointCostOfStat(nWis) + GetPointCostOfStat(nCha);
    if (nPointTotal > 30) {
        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
        sIllegal = "Illegal Stats Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
        WriteTimestampedLogEntry(sIllegal);
        SendMessageToAllDMs(sIllegal);
    }
    if (GetLegalHitPoints(oPC) < GetMaxHitPoints(oPC)) {
        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
        sIllegal = "Illegal Hit Points Detected - Name: " + GetName(oPC) + "; Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
        WriteTimestampedLogEntry(sIllegal);
        SendMessageToAllDMs(sIllegal);
    }
    if ((sName == "") || (GetBicFileName(oPC) == "")) {
        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal stats
        sIllegal = "Illegal Name Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
        SendMessageToPC(oPC, sIllegal);
        WriteTimestampedLogEntry(sIllegal);
        SendMessageToAllDMs(sIllegal);
    }
    if (GetLocalInt(oPC, "Accomplishments") != 0) {
        SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal accomplishments
        sIllegal = "Illegal Accomplishments Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
        SendMessageToPC(oPC, sIllegal);
        WriteTimestampedLogEntry(sIllegal);
        SendMessageToAllDMs(sIllegal);
    }
   
    /* check for not-yet-active HG specific feats */
    int i, nFeats = GetTotalKnownFeats(oPC);
    for (i = 0; i < nFeats; i++) {
        if (GetKnownFeat(oPC, i) >= 1995) {
            SetLocalInt(oPC, "Hacker", 2);//mark the character as having illegal feats
            sIllegal = "Illegal Feat " + IntToString(GetKnownFeat(oPC, i)) +
                " Detected - Account: " + GetPCPlayerName(oPC) + "; CDKey: " + GetPCPublicCDKey(oPC) + ".";
            SendMessageToPC(oPC, sIllegal);
            WriteTimestampedLogEntry(sIllegal);
            SendMessageToAllDMs(sIllegal);
        }
    }
}

You'll note that that chunk has checks unique to my PW, checking to make sure that they havent made a same-name character to benefit from tags.


In any case, after you fire the last stat checking call off, the PC will have a local int "Hacker" set to 2 if they cheated, and you can do what you will with them in any node thereafter. I wait till the end, clean up the extra locals, and send them to a Cheater's Cell area if the got tagged. Here's the script I use, everything until the else statement in the main function is relevant to you:

[code=auto:0]
#include "hg_inc"
#include "hgll_func_inc"
#include "nw_i0_tool"

string GetWeaponResRef (int nBaseItem) {
    switch (nBaseItem) {
        case BASE_ITEM_BASTARDSWORD:   return "nw_wswbs001";
        case BASE_ITEM_BATTLEAXE:      return "nw_waxbt001";
        case BASE_ITEM_CLUB:           return "nw_wblcl001";
        case BASE_ITEM_DAGGER:         return "nw_wswdg001";
        case BASE_ITEM_DIREMACE:       return "nw_wdbma001";
        case BASE_ITEM_DOUBLEAXE:      return "nw_wdbax001";
        case BASE_ITEM_DWARVENWARAXE:  return "x2_wdwraxe001";
        case BASE_ITEM_GREATAXE:       return "nw_waxgr001";
        case BASE_ITEM_GREATSWORD:     return "nw_wswgs001";
        case BASE_ITEM_HALBERD:        return "nw_wplhb001";
        case BASE_ITEM_HANDAXE:        return "nw_waxhn001";
        case BASE_ITEM_HEAVYFLAIL:     return "nw_wblfh001";
        case BASE_ITEM_KAMA:           return "nw_wspka001";
        case BASE_ITEM_KATANA:         return "nw_wswka001";
        case BASE_ITEM_KUKRI:          return "nw_wspku001";
        case BASE_ITEM_LIGHTFLAIL:     return "nw_wblfl001";
        case BASE_ITEM_LIGHTHAMMER:    return "nw_wblhl001";
        case BASE_ITEM_LIGHTMACE:      return "nw_wblml001";
        case BASE_ITEM_LONGSWORD:      return "nw_wswls001";
        case BASE_ITEM_MORNINGSTAR:    return "nw_wblms001";
        case BASE_ITEM_QUARTERSTAFF:   return "nw_wdbqs001";
        case BASE_ITEM_RAPIER:         return "nw_wswrp001";
        case BASE_ITEM_SCIMITAR:       return "nw_wswsc001";
        case BASE_ITEM_SCYTHE:         return "nw_wplsc001";
        case BASE_ITEM_SHORTSPEAR:     return "nw_wplss001";
        case BASE_ITEM_SHORTSWORD:     return "nw_wswss001";
        case BASE_ITEM_SICKLE:         return "nw_wspsc001";
        case BASE_ITEM_TRIDENT:        return "nw_wpltr001";
        case BASE_ITEM_TWOBLADEDSWORD: return "nw_wdbsw001";
        case BASE_ITEM_WARHAMMER:      return "nw_wblhw001";
        case BASE_ITEM_WHIP:           return "x2_it_wpwhip";
    }

    return "";
}

string GetFocusedWeapon (object oPC, int nBaseItem) {
    int i, nFeat;
    string sRes;

    for (i = 0; i <= BASE_ITEM_WHIP; i++) {
        nFeat = GetWeaponFocusFeat(i);

        if (nFeat > 0 && GetHasFeat(nFeat, oPC)) {
            sRes = GetWeaponResRef(i);
            if (sRes != "")
                return sRes;
        }
    }

    return GetWeaponResRef(nBaseItem);
}

void main() {
    object oPC = GetPCSpeaker();

    DeleteBaseAbilityMarkers(oPC);
    DeleteLocalInt(oPC, "FeatCheckCount");
    location voy;
    int nHack = GetLocalInt(oPC, "Hacker");

    if (nHack == 2) {
        DeleteLocalInt(oPC, "Hacker");
        voy = GetLocation(GetWaypointByTag("hacker_way"));
        AssignCommand(oPC, ActionJumpToLocation(voy));
    } else {
        if (TestStringAgainstPattern("**[TEST]**", GetName(oPC)))
            voy = GetLocation(GetWaypointByTag("funkywaypoint210"));
        else
            voy = GetLocation(GetWaypointByTag("voyage"));

        if (!HasItem(oPC, "PCList")) {
            int nGold = GetGold(oPC);

            if (nGold > 0)
                TakeGoldFromCreature(nGold, oPC, TRUE);

            if (GetHitDice(oPC) == 1) {
                object oItem;
                string sAmmo = "nw_wthdt001", sArmor = "nw_cloth001", sShield = "nw_ashsw001", sWeapon = "nw_wswdg001";

                switch (GetclassByPosition(1, oPC)) {
                    case class_TYPE_BARD:
                        sArmor  = "nw_cloth021";
                        sShield = "nw_it_mglove005";
                        break;

                    case class_TYPE_BARBARIAN:
                        sAmmo   = "nw_wthax001";
                        sArmor  = "nw_aarcl010";
                        sShield = "nw_ashlw001";
                        sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_BATTLEAXE);
                        break;

                    case class_TYPE_CLERIC:
                        sArmor  = "nw_aarcl004";
                        sWeapon = "nw_wblml001";
                        break;

                    case class_TYPE_DRUID:
                        sArmor  = "nw_aarcl008";
                        sWeapon = "nw_wspsc001";
                        break;

                    case class_TYPE_FIGHTER:
                        sAmmo   = "nw_wthax001";
                        sArmor  = "nw_aarcl006";
                        sShield = "nw_ashto001";
                        sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_LONGSWORD);
                        break;

                    case class_TYPE_MONK:
                        sAmmo   = "nw_wthsh001";
                        sArmor  = "nw_cloth016";
                        sShield = "nw_it_mglove008";
                        sWeapon = "nw_wspka001";
                        break;

                    case class_TYPE_PALADIN:
                        sAmmo   = "nw_wthax001";
                        sArmor  = "nw_aarcl011";
                        sShield = "nw_ashto001";
                        sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_WARHAMMER);
                        break;

                    case class_TYPE_RANGER:
                        sAmmo   = "nw_wamar001";
                        sArmor  = "nw_aarcl001";
                        sShield = "nw_wbwsh001";
                        sWeapon = GetFocusedWeapon(oPC, BASE_ITEM_SCIMITAR);
                        break;

                    case class_TYPE_ROGUE:
                        sAmmo   = "nw_wamar001";
                        sArmor  = "nw_aarcl001";
                        sShield = "nw_wbwsh001";
                        sWeapon = "nw_wswss001";
                        break;

                    case class_TYPE_SORCERER:
                        sAmmo   = "nw_wambo001";
                        sArmor  = "nw_cloth008";
                        sShield = "nw_wbwxl001";
                        break;

                    case class_TYPE_WIZARD:
                        sAmmo   = "nw_wambo001";
                        sArmor  = "nw_cloth005";
                        sShield = "nw_wbwxl001";

                        if (!GetKnowsSpell(SPELL_BURNING_HANDS,       oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_BURNING_HANDS);
                        if (!GetKnowsSpell(SPELL_CHARM_PERSON,        oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_CHARM_PERSON);
                        if (!GetKnowsSpell(SPELL_COLOR_SPRAY,         oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_COLOR_SPRAY);
                        if (!GetKnowsSpell(SPELL_ENDURE_ELEMENTS,     oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_ENDURE_ELEMENTS);
                        if (!GetKnowsSpell(SPELL_EXPEDITIOUS_RETREAT, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_EXPEDITIOUS_RETREAT);
                        if (!GetKnowsSpell(SPELL_GREASE,              oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_GREASE);
                        if (!GetKnowsSpell(SPELL_HORIZIKAULS_BOOM,    oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_HORIZIKAULS_BOOM);
                        if (!GetKnowsSpell(SPELL_ICE_DAGGER,          oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_ICE_DAGGER);
                        if (!GetKnowsSpell(SPELL_IDENTIFY,            oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_IDENTIFY);
                        if (!GetKnowsSpell(SPELL_IRONGUTS,            oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_IRONGUTS);
                        if (!GetKnowsSpell(SPELL_MAGE_ARMOR,          oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGE_ARMOR);
                        if (!GetKnowsSpell(SPELL_MAGIC_MISSILE,       oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGIC_MISSILE);
                        if (!GetKnowsSpell(SPELL_MAGIC_WEAPON,        oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_MAGIC_WEAPON);
                        if (!GetKnowsSpell(SPELL_NEGATIVE_ENERGY_RAY, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_NEGATIVE_ENERGY_RAY);
                        if (!GetKnowsSpell(SPELL_RAY_OF_ENFEEBLEMENT, oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_RAY_OF_ENFEEBLEMENT);
                        if (!GetKnowsSpell(SPELL_SCARE,               oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SCARE);
                        if (!GetKnowsSpell(SPELL_SHIELD,              oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SHIELD);
                        if (!GetKnowsSpell(SPELL_SLEEP,               oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SLEEP);
                        if (!GetKnowsSpell(SPELL_SUMMON_CREATURE_I,   oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_SUMMON_CREATURE_I);
                        if (!GetKnowsSpell(SPELL_TRUE_STRIKE,         oPC, class_TYPE_WIZARD)) AddKnownSpell(oPC, class_TYPE_WIZARD, 1, SPELL_TRUE_STRIKE);

                        break;

                    default:
                        break;
                }

                SetIdentified((oItem = CreateItemOnObject(sAmmo, oPC)), TRUE);
                SetItemStackSize(oItem, 99);

                SetIdentified(CreateItemOnObject(sArmor,  oPC), TRUE);
                SetIdentified(CreateItemOnObject(sShield, oPC), TRUE);
                SetIdentified(CreateItemOnObject(sWeapon, oPC), TRUE);

                SetIdentified(CreateItemOnObject("nw_it_mpotion001", oPC, 50), TRUE);
                SetIdentified(CreateItemOnObject("nw_it_torch001", oPC), TRUE);
                SetIdentified(CreateItemOnObject("nw_it_contain001", oPC), TRUE);
            }


            GiveGoldToCreature(oPC, 10000);
            CreateItemOnObject("pclist", oPC);
&
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Legit Checker Script
« Reply #6 on: January 14, 2011, 09:40:28 am »


               I had to create a similar system, however It wasnt as indepth as Funky's.



It basically determined if the player was a new player, or returning player, and if they were a New Player, it logged their base stats, and then on each level up, it would determine how much those stats had increased by, if it was over a certain threshold, it would transfer their character to a 'hacked' vault for analysis.



Have to say though, back when I ran Worlds of Rhun, 99.9% of the players were well behaved, and couldnt care less about hacking, it was a single person, who insisted on hacking his character, that prompted me to make the anti-hack system, and im happy to say, after his characters got caught everytime he tried hacking, he decided to move on to another server, which is just as well, because his hack attempts resulted in the server crashing once or twice.



The proverbial Fly in the Soup I guess - 1 guy spoils it for everyone, and makes it necessary to have such systems.
               
               

               
            

Legacy_virusman

  • Sr. Member
  • ****
  • Posts: 448
  • Karma: +0/-0
Legit Checker Script
« Reply #7 on: January 14, 2011, 03:26:34 pm »


               May be easier just to ban this one player.
               
               

               
            

Baaleos

  • Administrator
  • Hero Member
  • *****
  • Posts: 1916
  • Karma: +0/-0
Legit Checker Script
« Reply #8 on: January 14, 2011, 05:24:20 pm »


               I know its easier, but in some regards, I prefer to try and combat the issue, rather than avoid it.

I like a challenge.



I would rather allow him to play legit, and delete his hacked characters, than to ban him altogether.
               
               

               
            

Legacy_kalbaern

  • Hero Member
  • *****
  • Posts: 1531
  • Karma: +0/-0
Legit Checker Script
« Reply #9 on: January 14, 2011, 05:34:18 pm »


               

virusman wrote...

May be easier just to ban this one player.


Banning I always recommend, but ... deterents as above help more. Banning means "catching" idiots in the act and many have multiple CD keys, logins and will mask their IPs to continue their childish behavior. Ignoring them and having a automated system to deal with them makes them go away alot faster in the end and consumes little of an Admin's time.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Legit Checker Script
« Reply #10 on: January 14, 2011, 06:55:08 pm »


               Yes but at least in windows, ban is the only one way to get rid of them. Even if you manage to block every attempt to ha.ck his character, he can cras.h the server and you cannot fix this.

That fight itself may be fun, but if you do not know Baaleos ways they doing this, you have no chance. Even if you knew, you need linux nwnx plugins to be totally safe.
               
               

               


                     Modifié par ShaDoOoW, 14 janvier 2011 - 06:55 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Legit Checker Script
« Reply #11 on: January 14, 2011, 06:57:47 pm »


               As to banning vs code protections, banning is practically useless against some players, for reasons I prefer not to elaborate on (I know vman is aware of them). We wound up adding a second layer of protection, passwording, because cd key-playername bindings were insufficient.

Anyway, I just noticed that the forums truncated my code post, so here's the rest. I'm leaving out the rest of the truncated script above, because it's basically just server-specific stuff.

///////////////


In any case, after you fire the last stat checking call off, the PC will have a local int "Hacker" set to 2 if they cheated, and you can do what you will with them in any node thereafter. I wait till the end, clean up the extra locals, and send them to a Cheater's Cell area if the got tagged. Here's the script I use, everything until the else statement is relevant to you:


#include "hgll_func_inc"
#include "nw_i0_tool"
void main() {
    object oPC = GetPCSpeaker();
    DeleteBaseAbilityMarkers(oPC);
    DeleteLocalInt(oPC, "FeatCheckCount");
    location voy;
    int nHack = GetLocalInt(oPC, "Hacker");
    if (nHack == 2) {
    DeleteLocalInt(oPC, "Hacker");
    voy = GetLocation(GetWaypointByTag("hacker_way"));
    AssignCommand(oPC, ActionJumpToLocation(voy));
    } else {
        voy = GetLocation(GetWaypointByTag("voyage"));
        if (!HasItem(oPC, "PCList"))
            GiveGoldToCreature(oPC, 150);

        AssignCommand(oPC, ActionJumpToLocation(voy));
    }
}

Hope that's not too convoluted. It requires a minimum of 14 convo lines, though they can of course be of any length. It's seen extensive playtest on my servers, so I can vouchsafe against any false positives.

Funky
               
               

               
            

Legacy_Birdman076

  • Sr. Member
  • ****
  • Posts: 320
  • Karma: +0/-0
Legit Checker Script
« Reply #12 on: January 14, 2011, 11:58:42 pm »


               Thank you very much Funky, I am grabbing the conversation and copying the code to put this all together. I am planning on implimenting LL in the Rhun module I'm hosting I just haven't got around to it just yet. Off topic question: Will there be any problems with running LL and shayan's SSE leto version?
               
               

               
            

Legacy_Birdman076

  • Sr. Member
  • ****
  • Posts: 320
  • Karma: +0/-0
Legit Checker Script
« Reply #13 on: January 15, 2011, 01:08:20 am »


               Ok, got the conversation in a test mod, got the scripts set as posted, here is what is going on:

#include "hg_inc" is missing.

I opened up HGLL demo mod and looked for this one, no dice.

I get a ERROR: NO RIGHT BRACKET ON EXPRESSION for line 31 of fky_hakchk_feat
               
               

               


                     Modifié par Birdman076, 15 janvier 2011 - 01:08 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Legit Checker Script
« Reply #14 on: January 15, 2011, 03:37:48 am »


               You're going to find a number of functions in there that are missing, but not required. That was the unfortunate downside of giving you the updated version with proper hp checking. I imagine that one is tripping up on SendMessageToAllDMs, part of the debug. You can delete it and just rely on the WriteTimestamped... if you like. It compiles for me without hg_inc, however, which suggests to me there are other issues, likely with customizations from our hgll_func_inc include. Let me know what other compile errors you turn up.



Thanks,

Funky