Things get confusing really fast when bitcoin code is taken, modified, and the names of important items (methods, pointers, functions, etc. etc.) aren't changed.
I agree figuring out what the code does can be difficult. I've been analyzing it for almost a year, since I was made aware of it's flaws.
Perhaps it would make more sense if I mentioned method's signature:
unsigned int static GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake)
Second input parameter also determines block type on which
pIndexPrev and
pIndexPrevPrev point. When you generate nBits for PoW block, you pass
false.
pIndexPrev then points to PoW block as does
pIndexPrevPrev.
That is why I've written:
The same principle is used for PoS blocks. Just replace all occurences of PoW with PoS in text above.
That really means: "Just pass
true for
fProofOfStake"

It seems to me that the underlying imperative of this (original?) code is to save (.exe) file space by compressing code and reusing functions for multiple uses. Here
GetNextTargetRequired(...) is used for both PoW and PoS blocks. This results in actually slower code (potentially, unless the optimizer can save the day) and more opaque/obscure code to boot!
I see that that 2nd argument
fProofOfStake is tested over and over again. That is why I suggested that this PoW & PoS coin should have two separate sections inside
GetNextTargetRequired() and probably inside
GetLastBlockIndex(...) too! If this is called a lot, I see it called by
CBlock::AcceptBlock(), which is called by
ProcessBlock(...) I would think we could improve performance a wee bit by not testing something that isn't changing, over and over again!
I don't even understand the comment for
GetLastBlockIndex(...)// ppcoin: find last block index up to pindex
const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake)What is pindex, and what is the last block index that this is finding? For PoS and PoW flags and the type of the blocks pointed to by pindex? Or should I know what type that is already? This comment (documentation???) doesn't really help me at all (LOL) No wonder it has taken you a year to
grok this! And no wonder the bitcoin source code, after 6 years (!), still isn't really understood by anyone in an understandable way! And that is why the changes are so glacially slow. There is no "consensus" library code (.a, .dll, .lib etc.) because no one knows WTF is going on

...But isn't time counted (on the average) from the moment of the PoS block acceptance?...
Time is taken into account later in the same function. First
nTargetSpacing is calculated. Then
real time difference is
thrown into equation. If those two blocks pointed by
pIndexPrev and
pIndexPrevPrev are less than
nTargetSpacing apart, difficulty is raised (nBits get's lowered).
I don't thionk I can even attempt to understand your paragraph above until I can understand the (sub)function
GetLastBlockIndex(..) 
I have no idea what that means (LOL). Correct score? Trust calculation? What and where are those items?
Chaintrust is what I had in mind. It's
all over there.
Yikes! More ill-documented functions,
InvalidChainFound(...)
CBlockIndex::GetBlockTrust()
IsSuperMajority(...)I think it is more important to document and rename (refactor if you will) ill named variables (nouns) and functions (verbs) so that one can read the code and not have to constantly translate what it says into what it means! It is impossible to do that if one doesn't know what it means!!
I have no problem with changes, but at least clean up and clarify (make more transparent, understandable, clear) what surrounds your changes.
Actually I'd like to do it to do it to all of the bitcoin source and the source of every other crypto currency. I would like it if Yacoin was the first to do it!
It would be so easy then to make replaceable libraries, build new GUIs, add features, etc. etc., but hey, nobody reads Martin Fowler, Joel Spolsky, ... anymore. Or even knows who they are!

Ron