```\nfunction _castVote(address _voter, uint256 _proposalId, uint8 _support) internal returns (uint) {\n    // Only Active proposals can be voted on\n    if (state(_proposalId) != ProposalState.Active) revert InvalidStatus();\n    \n    // Only valid values for _support are 0 (against), 1 (for), and 2 (abstain)\n    if (_support > 2) revert InvalidInput();\n\n    Proposal storage proposal = proposals[_proposalId];\n\n    // If the voter has already voted, revert        \n    Receipt storage receipt = proposal.receipts[_voter];\n    if (receipt.hasVoted) revert AlreadyVoted();\n\n    // Calculate the number of votes a user is able to cast\n    // This takes into account delegation and community voting power\n    uint24 votes = (staking.getVotes(_voter)).toUint24();\n\n    // Update the proposal's total voting records based on the votes\n    if (_support == 0) {\n        proposal.againstVotes = proposal.againstVotes + votes;\n    } else if (_support == 1) {\n        proposal.forVotes = proposal.forVotes + votes;\n    } else if (_support == 2) {\n        proposal.abstainVotes = proposal.abstainVotes + votes;\n    }\n\n    // Update the user's receipt for this proposal\n    receipt.hasVoted = true;\n    receipt.support = _support;\n    receipt.votes = votes;\n\n    // Make these updates after the vote so it doesn't impact voting power for this vote.\n    ++totalCommunityScoreData.votes;\n\n    // We can update the total community voting power with no check because if you can vote, \n    // it means you have votes so you haven't delegated.\n    ++userCommunityScoreData[_voter].votes;\n\n    return votes;\n}\n```\n