[RELWIP] Skyrim -Elys- Uncapper

Post » Mon May 21, 2012 10:50 am

thank you elys and ianpatt!
User avatar
~Sylvia~
 
Posts: 3474
Joined: Thu Dec 28, 2006 5:19 am

Post » Mon May 21, 2012 5:53 pm


You can all thanks ianpatt for it :biggrin:


Already have...and also BIG thanks to you too Ely. :)
User avatar
Melissa De Thomasis
 
Posts: 3412
Joined: Tue Feb 27, 2007 6:52 pm

Post » Mon May 21, 2012 12:07 pm

Big thanks to Elys and Ianpatt for working to get an update out.
User avatar
Richard Dixon
 
Posts: 3461
Joined: Thu Jun 07, 2007 1:29 pm

Post » Mon May 21, 2012 3:56 pm

@ianpatt
Thanks a million, did not mean to steal your valuable time, but I will not say nay to such a gift!

@Elys
Thanks a million as well - read Ian's post at work, and got home and wham! :smile:
User avatar
Arnold Wet
 
Posts: 3353
Joined: Fri Jul 07, 2006 10:32 am

Post » Mon May 21, 2012 2:56 am

Thanks ianpatt and Elys!
User avatar
Umpyre Records
 
Posts: 3436
Joined: Tue Nov 13, 2007 4:19 pm

Post » Mon May 21, 2012 8:08 am

Thank you very much to to ianpatt and Elys... I can finally play with the update! I have been reticent as I have several skills over 100 and didn't know what would happen if I tried to play sans the Uncapper plugin!
User avatar
Alexander Horton
 
Posts: 3318
Joined: Thu Oct 11, 2007 9:19 pm

Post » Mon May 21, 2012 11:08 am

Below is the source code of the Uncapper v1.55 for Skyrim 1.4.21, for the few interested :smile:

Spoiler

library SKSE_Elys_Uncapper;{$R *.res}uses  Windows, SysUtils, IniFiles, Classes;type  PluginHandle = Longword;  SKSEInterface = packed record	skseVersion: Longword;	runtimeVersion: Longword;	editorVersion: Longword;	isEditor: Longword;	QueryInterface: procedure(id: Longword); cdecl;	GetPluginHandle: function: PluginHandle; cdecl;  end;  PluginInfo = packed record  const	kInfoVersion: Longword = 1;  var	infoVersion: Longword;	name: PAnsiChar;	version: Longword;  end;  TPerkByLevel = record	Level: Word;	Perks: Byte;  end;const  kPluginHandle_Invalid = $FFFFFFFF;  SKYRIM_VER = $04150000;  SKSE_VER = $01040080;  PLUGIN_VER = $01050050;  oPLAYER = Pointer($0137DC6C);  AlterationID = 18;  ArcheryID = 8;  AlchemyID = 16;  ConjurationID = 19;  BlockID = 9;  LightArmorID = 12;  DestructionID = 20;  HeavyArmorID = 11;  LockpickingID = 14;  EnchantingID = 23;  OneHandedID = 6;  PickpocketID = 13;  IllusionID = 21;  SmithingID = 10;  SneakID = 15;  RestorationID = 22;  TwoHandedID = 7;  SpeechID = 17;var  Enabled: Boolean = False;  SkillEffectFormulasCap: Single;  pSkillEffectFormulasCap: PSingle;  FixSneakOver100CheckCode: packed Array [0 .. 5] of Byte = (	$9E, // sahf	$9B, // wait	$DF,$E0, // fstsw ax	$90, // nop	$73 // jae  );  SkillCaps: packed Array [6 .. 23] of Single;  SkillMults: Array [6 .. 23] of Single;  PerksPerLevel: Array of TPerkByLevel;  LastValidedSkill: Longword;  CurrentSkillCap : Single;  CurrentSkillLevel : Single;  pSkillCapPatch: Pointer;  pSkillCapPatch2: Pointer;  pIncreasePerkPool : Pointer;  pIncreaseSkillExp : Pointer;  SLParam1, SLParam2 : Single;  GetActorLevel: function(a1, a2: Integer; This: Pointer): Word; cdecl;  CalculateExpForNextLevel: function( SkillLevel, SLParam1, SLParam2 : Single ): Single; cdecl;  GetSkillCoefficients: function(a1, a2, a3 : Longint; a4, a5: PSingle): Byte; cdecl;function Overwrite(Address: Pointer; Data: Pointer; Size: Longword): Boolean;var  OldFlag: Longword;begin  Result := False;  if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, @OldFlag) then	Move(Data^, Address^, Size)  else  begin	MessageBox(0, 'SKSE Elys Uncapper could not modify Skyrim in memory. PLEASE CLOSE THE GAME NOW TO AVOID POTENTIAL GAME INCONSISTANCIES OR CORRUPTION', 'Error', MB_ICONERROR);	Exit;  end;  Result := True;end;function SetFF15Call(Address: Pointer; Target: Pointer): Boolean;var  Jmp: packed record   Code: Word;   Target: Pointer;  end;begin  Jmp.Code := $15FF;  Jmp.Target := Target;  Result := Overwrite(Address, @Jmp, 6);end;function SetE8Call(Address: Pointer; Target: Pointer): Boolean;var  Jmp: packed record	Code: Byte;	Target: Longword;  end;begin  Jmp.Code := $E8;  Jmp.Target := Longword(Target) - Longword(Address) - 5;  Result := Overwrite(Address, @Jmp, 5);end;Function ReplaceE8CallTarget(Caller: PByte; Target: Pointer): Boolean;var  Address: Longword;begin  Address := Longword(Target) - Longword(Caller) - 5;  Result := Overwrite(Pointer(Caller + 1), @Address, 4);end;function hook_GetSkillCoefficients(a1, a2, a3 : Longint; a4, a5: PSingle): Byte; cdecl;begin  Result := GetSkillCoefficients(a1, a2, a3, a4, a5);  SLParam1 := a4^;  SLParam2 := a5^end;procedure IncreasePerkPool;const  PerkOffset = $6C9; // offset to update with each new Skyrim versionvar  This: PByte;  Level: Word;  i: Integer;  b: Integer;begin  asm	pushad	mov This, eax  end;  Level := GetActorLevel(0, 0, This);  b:= -1;  for i := 0 to High(PerksPerLevel) do	if Level < PerksPerLevel[i].Level then	  break	else if Level = PerksPerLevel[i].Level then	begin	  b := PerksPerLevel[i].Perks;	  break;	end	else	  b := PerksPerLevel[i].Perks;  if b >= 0 then	b := (This + PerkOffset)^ + b  else	b := (This + PerkOffset)^ + 1;  if (This + PerkOffset)^ < b then	(This + PerkOffset)^ := b;  asm	popad  end;end;procedure IncreaseSkillExp_Sub(This: PByte; pExpEarned: PSingle); stdcall;begin  if (PSingle(This + 8)^ = 0) and (CurrentSkillLevel < SkillCaps[LastValidedSkill]) then	begin	  PSingle(This + 4)^ := 0;	  PSingle(This + 8)^ := PSingle(This + 4)^ + CalculateExpForNextLevel(CurrentSkillLevel+1, SLParam1, SLParam2);	end;  pExpEarned^ := pExpEarned^ * SkillMults[LastValidedSkill];end;procedure IncreaseSkillExp;asm  mov [edx+6B4h], ebx  lea ebx, [esp+24h]  pushad  push ebx  push esi  call IncreaseSkillExp_Sub  popadend;procedure GetSkill;asm  mov ecx,3F800000h  mov LastValidedSkill, esiend;procedure IsValidSkill;asmlea eax, [edi-6]mov ebp, ecxmov LastValidedSkill, ediend;procedure SkillCapPatch;begin	CurrentSkillCap := SkillCaps[LastValidedSkill];  asm	fld CurrentSkillCap  end;end;procedure SkillCapPatch2;asm  mov eax, [esp+12]  mov CurrentSkillLevel, eax  jmp SkillCapPatchend;function InitOptions: Boolean;const  INI_ERROR = 'Error: Skyrim_Elys_Uncapper.ini';  IS_INVALID_VALUE = 'http://forums.bethsoft.com/topic/1287595-relwip-skyrim-elys-uncapper/is not a valid value for';  MAX_LEVEL = 10000;var  Filename: String;  IniFile: TMemIniFile;  Strings: TStringList;  i, j: Integer;  Level: Integer;  Perks: Integer;  PerksPerLevelIndex: Integer;  function SafeReadInteger(const name: String; Default: Integer): Integer;  var	idx: Integer;  begin	idx := Strings.IndexOfName(Name);	if idx < 0 then	  Result := Default	else if TryStrToInt(Strings.ValueFromIndex[idx], Result) and (Result >= 0) and (Result <= MAX_LEVEL) then	  Exit;	Result := Default;	MessageBox(0, PChar(Strings.ValueFromIndex[idx] + IS_INVALID_VALUE + Name + '.'), INI_ERROR, MB_ICONERROR);  end;  function SafeReadFloat(const name: String; Default: Single): Single;  var	idx: Integer;  begin	idx := Strings.IndexOfName(Name);	if idx < 0 then	  Result := Default	else if TryStrToFloat(Strings.ValueFromIndex[idx], Result) and (Result >= 0) and (Result <= MAX_LEVEL) then	  Exit;	Result := Default;	MessageBox(0, PChar(Strings.ValueFromIndex[idx] + IS_INVALID_VALUE + Name + '.'), INI_ERROR, MB_ICONERROR);  end;  function SafeReadBool(const name: String; Default: Boolean): Boolean;  var	idx: Integer;  begin	idx := Strings.IndexOfName(Name);	if idx < 0 then	  Result := Default	else if not TryStrToBool(Strings.ValueFromIndex[idx], Result) then	begin	  Result := Default;	  MessageBox(0, PChar(Strings.ValueFromIndex[idx] + IS_INVALID_VALUE + Name + '.'), INI_ERROR, MB_ICONERROR);	  Exit;	end;  end;begin  Result := True;  SetLength(Filename, MAX_PATH + 1);  GetModuleFileNameW(HInstance, @Filename[1], MAX_PATH + 1);  IniFile := TMemIniFile.Create(ExtractFilePath(Filename) + 'SKSE_Elys_Uncapper.ini');  PerksPerLevelIndex := 0;  try	Strings := TStringList.Create;	try	  FormatSettings.DecimalSeparator := '.';	  SetLength(TrueBoolStrs, 2);	  TrueBoolStrs[0] := 'True';	  TrueBoolStrs[1] := '1';	  SetLength(FalseBoolStrs, 2);	  FalseBoolStrs[0] := 'False';	  FalseBoolStrs[1] := '0';	  IniFile.ReadSectionValues('General', Strings);	  Enabled := SafeReadBool('bEnabled', False);	  SkillEffectFormulasCap := SafeReadInteger('iSkillEffectFormulasCap', 100);	  Strings.Clear;	  IniFile.ReadSectionValues('SkillCaps', Strings);	  SkillCaps[AlterationID] := SafeReadInteger('iAlteration', 100);	  SkillCaps[ArcheryID] := SafeReadInteger('iArchery', 100);	  SkillCaps[AlchemyID] := SafeReadInteger('iAlchemy', 100);	  SkillCaps[ConjurationID] := SafeReadInteger('iConjuration', 100);	  SkillCaps[BlockID] := SafeReadInteger('iBlock', 100);	  SkillCaps[LightArmorID] := SafeReadInteger('iLightArmor', 100);	  SkillCaps[DestructionID] := SafeReadInteger('iDestruction', 100);	  SkillCaps[HeavyArmorID] := SafeReadInteger('iHeavyArmor', 100);	  SkillCaps[LockpickingID] := SafeReadInteger('iLockpicking', 100);	  SkillCaps[EnchantingID] := SafeReadInteger('iEnchanting', 100);	  SkillCaps[OneHandedID] := SafeReadInteger('iOneHanded', 100);	  SkillCaps[PickpocketID] := SafeReadInteger('iPickpocket', 100);	  SkillCaps[IllusionID]:= SafeReadInteger('iIllusion', 100);	  SkillCaps[SmithingID] := SafeReadInteger('iSmithing', 100);	  SkillCaps[SneakID] := SafeReadInteger('iSneak', 100);	  SkillCaps[RestorationID]:= SafeReadInteger('iRestoration', 100);	  SkillCaps[TwoHandedID]  := SafeReadInteger('iTwoHanded', 100);	  SkillCaps[SpeechID] := SafeReadInteger('iSpeech', 100);	  Strings.Clear;	  IniFile.ReadSectionValues('SkillExpGainMults', Strings);	  SkillMults[AlterationID] := SafeReadFloat('fAlteration', 1);	  SkillMults[ArcheryID] := SafeReadFloat('fArchery', 1);	  SkillMults[AlchemyID] := SafeReadFloat('fAlchemy', 1);	  SkillMults[ConjurationID] := SafeReadFloat('fConjuration', 1);	  SkillMults[BlockID] := SafeReadFloat('fBlock', 1);	  SkillMults[LightArmorID] := SafeReadFloat('fLightArmor', 1);	  SkillMults[DestructionID] := SafeReadFloat('fDestruction', 1);	  SkillMults[HeavyArmorID] := SafeReadFloat('fHeavyArmor', 1);	  SkillMults[LockpickingID] := SafeReadFloat('fLockpicking', 1);	  SkillMults[EnchantingID] := SafeReadFloat('fEnchanting', 1);	  SkillMults[OneHandedID] := SafeReadFloat('fOneHanded', 1);	  SkillMults[PickpocketID] := SafeReadFloat('fPickpocket', 1);	  SkillMults[IllusionID] := SafeReadFloat('fIllusion', 1);	  SkillMults[SmithingID] := SafeReadFloat('fSmithing', 1);	  SkillMults[SneakID] := SafeReadFloat('fSneak', 1);	  SkillMults[RestorationID] := SafeReadFloat('fRestoration', 1);	  SkillMults[TwoHandedID] := SafeReadFloat('fTwoHanded', 1);	  SkillMults[SpeechID] := SafeReadFloat('fSpeech', 1);	  Strings.Clear;	  IniFile.ReadSectionValues('PerksPerLevelAndAbove', Strings);	  SetLength(PerksPerLevel, Strings.Count);	  For i := 0 to Strings.Count - 1 do		if TryStrToInt(Strings.Names[i], Level) and (Level > 0) and (Level <= MAX_LEVEL) then		  if TryStrToInt(Strings.ValueFromIndex[i], Perks) and (Perks >= 0) and (Perks <= 255) then		  begin			PerksPerLevel[PerksPerLevelIndex].Level := Level;			PerksPerLevel[PerksPerLevelIndex].Perks := Perks;			Inc(PerksPerLevelIndex);		  end		  else			MessageBox(0, PChar(Strings[i] + ' is not a correct Perks value for [PerksPerLevelAndAbove].'), INI_ERROR, MB_ICONERROR)		else		  MessageBox(0, PChar(Strings[i] + ' is not a correct Level value for [PerksPerLevelAndAbove].'), INI_ERROR, MB_ICONERROR);	finally	  Strings.Free;	end;	SetLength(PerksPerLevel, PerksPerLevelIndex);	for j := High(PerksPerLevel) - 1 downto 1 do	  for i := 0 to j do		if PerksPerLevel[i].Level > PerksPerLevel[i + 1].Level then		begin		  Level := PerksPerLevel[i].Level;		  Perks := PerksPerLevel[i].Perks;		  PerksPerLevel[i].Level := PerksPerLevel[i + 1].Level;		  PerksPerLevel[i].Perks := PerksPerLevel[i + 1].Perks;		  PerksPerLevel[i + 1].Level := Level;		  PerksPerLevel[i + 1].Perks := Perks;		end;  except	MessageBox(0, 'SKSE Elys Uncapper encountered an error while attempting to read SKSE_Elys_Uncapper.ini. The plugin is not enabled', 'Error', MB_ICONERROR);	Result := False;  end;  IniFile.Free;end;Function SKSEPlugin_Query(const skse: SKSEInterface; var Info: PluginInfo): Boolean; cdecl;begin  Info.infoVersion := PluginInfo.kInfoVersion;  Info.name := 'SKSE_Elys_Uncapper';  Info.version := PLUGIN_VER;  Result := False;  if skse.isEditor <> 0 then	Exit;  if skse.skseVersion < SKSE_VER then  begin	MessageBox(0, 'SKSE Elys Uncapper requires SKSE Version 1.4.8 or above.', 'Error: Plugin not enabled', MB_ICONERROR);	Exit;  end;  if skse.runtimeVersion <> SKYRIM_VER then  begin	MessageBox(0, 'SKSE Elys Uncapper only supports Skyrim Version 1.4.21.', 'Error: Plugin not enabled', MB_ICONERROR);	Exit;  end;  Result := True;end;Function SKSEPlugin_Load(const skse: SKSEInterface): Boolean; cdecl;begin  Result := False;  If not InitOptions then	Exit;  if not Enabled then  begin	Result := True;	Exit;  end;  GetActorLevel := Pointer($008C30F0);  CalculateExpForNextLevel := Pointer($00751250);  GetSkillCoefficients := Pointer($005A85F0);  if not SetE8Call(Pointer($0075161F), @IsValidSkill) then // IsValidSkill	Exit;  if not SetE8Call(Pointer($007514F2), @GetSkill) then // GetSKill	Exit;  pSkillCapPatch := @SkillCapPatch;  if not SetFF15Call(PByte(@CalculateExpForNextLevel)+7, @pSkillCapPatch) then // Skill Exp Curve Cap	Exit;  if not SetFF15Call(Pointer($0075174D), @pSkillCapPatch) then // Skill Cap	Exit;  if not SetFF15Call(Pointer($00751869), @pSkillCapPatch) then // Skill Cap	Exit;  pSkillCapPatch2 := @SkillCapPatch2;  if not SetFF15Call(Pointer($0075164B), @pSkillCapPatch2) then // Skill Cap 2	Exit;  if not ReplaceE8CallTarget(PByte($0075168B), @hook_GetSkillCoefficients) then // sub_650A70 hook;	Exit;  pIncreasePerkPool := @IncreasePerkPool;  if not SetFF15Call(Pointer($0087BCB9), @pIncreasePerkPool) then // Perk Management. Dont forget update offset inside function	Exit;  pIncreaseSkillExp := @IncreaseSkillExp;  if not SetFF15Call(Pointer($00751734), @pIncreaseSkillExp) then // Skill Exp Mult	Exit;  pSkillEffectFormulasCap := @SkillEffectFormulasCap;  if not Overwrite(Pointer($005AA2F9), @pSkillEffectFormulasCap, 4) then // Uncap formulas	Exit;  if not Overwrite(Pointer($006C78EA), @FixSneakOver100CheckCode, 6) then // Sneak Formula Cap Fix	Exit;  Result := True;end;exports  SKSEPlugin_Query, SKSEPlugin_Load;beginend.
User avatar
Laura
 
Posts: 3456
Joined: Sun Sep 10, 2006 7:11 am

Post » Mon May 21, 2012 2:16 pm

Great news, thanks for the efforts Elys & IanPatt. :)
User avatar
Schel[Anne]FTL
 
Posts: 3384
Joined: Thu Nov 16, 2006 6:53 pm

Post » Mon May 21, 2012 8:13 am

Just goes to show, sometimes a different set of eyes are all that is needed. I'm glad you got the Uncapper updated.

Thank you Elys and IanPatt.
User avatar
Sammygirl500
 
Posts: 3511
Joined: Wed Jun 14, 2006 4:46 pm

Post » Mon May 21, 2012 11:38 am

Thanks for the update Elys and Ian
User avatar
Angela
 
Posts: 3492
Joined: Mon Mar 05, 2007 8:33 am

Post » Mon May 21, 2012 6:39 pm

huzzah! i wasn't ever really worried, but it's great to see teamwork here :D thanks ianpatt and elys!
User avatar
oliver klosoff
 
Posts: 3436
Joined: Sun Nov 25, 2007 1:02 am

Post » Mon May 21, 2012 10:34 am

Wonderful! To everyone involved, thanks a million!
User avatar
carrie roche
 
Posts: 3527
Joined: Mon Jul 17, 2006 7:18 pm

Post » Mon May 21, 2012 5:07 am

I can't express how happy I was to see an update that's compatible with the patch.
After using the uncapper for several years with Oblivion I'd have felt something really amiss without.

Magic. :banana:
User avatar
Horror- Puppe
 
Posts: 3376
Joined: Fri Apr 13, 2007 11:09 am

Post » Mon May 21, 2012 6:53 am

Since ianpatt kindly provided the new needed addresses for the Uncapper, I was able to update it.

So you can now download V1.55. No new features, just support of Skyrim 1.4.21.

You can all thanks ianpatt for it :biggrin:

I'm gonna reply to some other posts in this thread as well as posting the new source code, but I'm in a rush, so later.....

You guys are both awesome. Thank you a ton for this. :)

With any luck, Bethesda won't rearrange the code so significantly again with Skyrim, as I have a feeling they won't update again unless absolutely necessary once the CK is out.

There'll probably be another update if and when an expansion comes out, though.
User avatar
Krystal Wilson
 
Posts: 3450
Joined: Wed Jan 17, 2007 9:40 am

Post » Mon May 21, 2012 5:22 am

Can I use my old .ini file with this? It's a little of a pain to reconfigure. Possible? Absolutely. Just a pain. You guys ROCK!! Thanks Ian and Elys for making my game more enjoyable again.
User avatar
Natasha Callaghan
 
Posts: 3523
Joined: Sat Dec 09, 2006 7:44 pm

Post » Mon May 21, 2012 3:12 am

Thank you so much! ianpatt and Elys! You both are genius modders.
User avatar
clelia vega
 
Posts: 3433
Joined: Wed Mar 21, 2007 6:04 pm

Post » Mon May 21, 2012 7:13 am

My thanks also to both ianpatt and Elys. This is truly one of those must have mods, thank you!
User avatar
SHAWNNA-KAY
 
Posts: 3444
Joined: Mon Dec 18, 2006 1:22 pm

Previous

Return to V - Skyrim