How to properly use raycasting for interacting with objects

Got full auto working, moving onto grenades and shotguns.

Ii think the shotguns use either the fullauto or singleauto scripts, and the grenades just rotate all their children. It would be nice if you could figure out a way to have the amount of rays for shotguns and nades just an attribute number instead of having to copy a bunch of entities.

Perhaps binding the raycast function to repeat until some atribute number is reached?

Ok going to do that that sounds fun.

Also how would you prefer to be credited?

Idk just put my name somewhere I guess

ok never mind doing the shotgun without the entitites would be a huge pain so thats a tomorrow issue for me.

we will now just have to deal with the pain of duplicating an entity forty times for a shotgun

No I was thinking:

Check if variable is equal to attribute number
randomly rotate entity and cast ray
Do ray stuff
Increase variable
bind

Would that work?

ooh thats smart i did not think of that.

I would do it myself im just not too sure how binding works.

binding? why would we need that? this can be solved with just a for loop.

Oh, well im not too sure how that works either. I am not limited by ability, but knowledge.

For loops basically iterate a variable until it reaches a certain value

I assume you are capable of doing this?

Yes, it is rather simple.

So if singleauto and fullauto are finished can you send them over?

Alright
SingleAuto

var Singleauto = pc.createScript('singleauto');

// THE DELAY BETWEEN SHOTS BEFORE THE PLAYER CAN FIRE AGAIN IN SECONDS, IN BURST MODE THIS IS THE TIME BETWEEN BURSTS
Singleauto.attributes.add("thedelay", {
    type: "number",
    default: 1
});

// INHERENT INACCURACY WHEN NOT AIMING
Singleauto.attributes.add("inaccuracy", {
    type: "number",
    default: 10
});

// ACCURACY WHEN AIMING, USUALLY LEAVE THIS AT ZERO UNLESS YOU ARE DOING WEIRD STUFF
Singleauto.attributes.add("accuracy", {
    type: "number",
    default: 0
});

// CHECKS IF THE GUN IS BURST FIRE
Singleauto.attributes.add("isburst", {
    type: "boolean"
});

// TIME BETWEEN BULLETS IN SINGLE BURST IN SECONDS. ONLY ACTIVE IF ISBURST IS TRUE
Singleauto.attributes.add("burstdelayS", {
    type: "number"
});

// TIME BETWEEN BULLETS IN SINGLE BURST IN RPM. ONLY ACTIVE IF ISBURST IS TRUE
Singleauto.attributes.add("burstdelayRPM", {
    type: "number"
});

// NUMBER OF BULLETS IN BURST. ONLY ACTIVE IF ISBURST IS TRUE
Singleauto.attributes.add("burstnumber", {
    type: "number"
});

// ENEMY TAG IT DAMAGES
Singleauto.attributes.add("enemyTag", {
    type: "string",
    default: "enemy"
});

// BULLET MAX RANGE
Singleauto.attributes.add("range", {
    type: "number",
    default: 10000
});

Singleauto.attributes.add("shotgun", {
    type:"boolean",
    default:false
});

Singleauto.attributes.add("bulletCount", {
    type:"number",
    default:1
});

Singleauto.prototype.initialize = function() {
    this.timer = 0;
    this.currentburst = 1;
    this.canburst = false;
};

Singleauto.prototype.update = function(dt) {
    this.entity.children.forEach((entity) => {
        entity.enabled = false;
    });

    // ONLY USED FOR BURST. REMEMBER THAT SECONDS TAKES PRIORITY OVER RPM, SO IF RPM IS TO BE USED SECONDS MUST BE AT ZERO. WHAT THIS FUNCTION ACTUALLY DOES HERE IS CONVERT THE RPM TO SECONDS, WHICH IS WHAT THE SCRIPT ACTUALLY USES
    if (this.burstdelayS === 0) {
        Realrate = (1 / (this.burstdelayRPM / 60))
    } else {
        Realrate = this.burstdelayS
    }

    // THREE DEBUG FUNCTIONS BELOW CAN BE REMOVED. MESSED UP BY BURST MODE BUT THIS IS ONLY DEBUG INFO SO WHO CARES.
    FirerateinS = this.thedelay
    FirerateinRPM = Math.round(60 / this.thedelay)
    Firemode = "SINGLE AUTO"

    // CHECKS IF PLAYER IS AIMING AND ACCURACY IS ADJUSTED
    if (this.app.mouse.isPressed(pc.MOUSEBUTTON_RIGHT)) {
        this.entity.setLocalEulerAngles((Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2));
    } else {
        this.entity.setLocalEulerAngles((Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2));
    }

    this.timer += dt;

    // CHECKS TO MAKE SURE BULLETS IS MORE THAN ZERO, THAT LEFT CLICK IS CLICKED, AND IF THE TIMER IS GREATER THAN THE DELAY
    if (Bullets > 0) {
        if (this.app.mouse.wasPressed(pc.MOUSEBUTTON_LEFT)) {
            if (this.timer > this.thedelay) {
                if(!this.shotgun) {
                    anglePos = this.entity.forward.clone();
                    anglePos.scale(this.range);
                    from = this.entity.getPosition();
		            result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                    this.entity.children.forEach((entity) => {
                        entity.enabled = true;
                    });
		            if(result){
			            if(result.entity.tags.has(this.enemyTag)) {
		                    result.entity.translateLocal(0,-50000,0);
				            result.entity.sound.play("sound");
				            Grams += 1;
			            };
                    };
                } else {
                    for(i=0;i<this.bulletCount;i++) {
                        if (this.app.mouse.isPressed(pc.MOUSEBUTTON_RIGHT)) {
                            this.entity.setLocalEulerAngles((Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2));
                        } else {
                            this.entity.setLocalEulerAngles((Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2));
                        };
                        anglePos = this.entity.forward.clone();
                        anglePos.scale(this.range);
                        from = this.entity.getPosition();
		                result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                        this.entity.children.forEach((entity) => {
                            entity.enabled = true;
                        });
		                if(result){
			                if(result.entity.tags.has(this.enemyTag)) {
		                        result.entity.translateLocal(0,-50000,0);
				                result.entity.sound.play("sound");
				                Grams += 1;
			                };
                        };
                    }
                };
                this.entity.sound.play("sound");
                this.timer = 0;
                Bullets -= 1;
                Missing += 1;
                Recoilburst = 1;
                this.canburst = true;
                //this.currentburst += 1;
            };
        };

        // BURSTS GUN ONLY IF ISBURST IS TRUE
        if (this.isburst === true) {
            if (this.currentburst < this.burstnumber) {
                if (this.canburst === true) {
                    if (this.timer > Realrate) {
                        if(!this.shotgun) {
                            anglePos = this.entity.forward.clone();
                            anglePos.scale(this.range);
                            from = this.entity.getPosition();
		                    result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                            this.entity.children.forEach((entity) => {
                                entity.enabled = true;
                            });
		                    if(result){
			                    if(result.entity.tags.has(this.enemyTag)) {
		                            result.entity.translateLocal(0,-50000,0);
				                    result.entity.sound.play("sound");
				                    Grams += 1;
			                    };
                            };
                        } else {
                            for(i=0;i<this.bulletCount;i++) {
                                if (this.app.mouse.isPressed(pc.MOUSEBUTTON_RIGHT)) {
                                    this.entity.setLocalEulerAngles((Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2));
                                } else {
                                    this.entity.setLocalEulerAngles((Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2));
                                };
                                anglePos = this.entity.forward.clone();
                                anglePos.scale(this.range);
                                from = this.entity.getPosition();
		                        result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                                this.entity.children.forEach((entity) => {
                                    entity.enabled = true;
                                });
		                        if(result){
			                        if(result.entity.tags.has(this.enemyTag)) {
		                                result.entity.translateLocal(0,-50000,0);
				                        result.entity.sound.play("sound");
				                        Grams += 1;
			                        };
                                };
                            }
                        }
                        this.entity.sound.play("sound");
                        this.timer = 0;
                        Bullets -= 1;
                        Missing += 1;
                        Recoilburst = 1;
                        this.currentburst += 1;
                    }
                }
            }
        }

    if (this.currentburst === this.burstnumber) {
        this.currentburst = 1;
        this.canburst = false;
    } else if (Bullets === 0) {
        this.currentburst = 1;
        this.canburst = false;
    }
    }
};

FullAuto

var Fullauto = pc.createScript('fullauto');
// REMEMBER THAT THIS SCRIPT IS ATTACHED TO THE BULLET PARENT ENTITY

// THIS IS THE FIRE RATE IN SECONDS. LEAVE AT ZERO IF YOU WANT TO USE RPM
Fullauto.attributes.add("firerateS", {
    type: "number",
    default: 0
});

// THIS IS THE FIRE RATE IN ROUNDS PER MINUTE
Fullauto.attributes.add("firerateRPM", {
    type: "number",
    default: 0.1
});

// INHERENT INACCURACY WHEN NOT AIMING
Fullauto.attributes.add("inaccuracy", {
    type: "number",
    default: 10
});

// ACCURACY WHEN AIMING, USUALLY LEAVE THIS AT ZERO UNLESS YOU ARE DOING WEIRD STUFF
Fullauto.attributes.add("accuracy", {
    type: "number",
    default: 0
});

// TAG OF THE ENEMY
Fullauto.attributes.add("enemyTag", {
	type:"string",
	default:"enemy"
});

// BULLET MAX RANGE
Fullauto.attributes.add("range", {
	type:"number",
	default: 10000
});

Fullauto.attributes.add("shotgun", {
    type:"boolean",
    default:false
});

Fullauto.attributes.add("bulletCount", {
    type:"number",
    default:1
});

Fullauto.prototype.initialize = function() {
    this.timer = 0;
};

Fullauto.prototype.update = function(dt) {

    this.entity.children.forEach((entity) => {
        entity.enabled = false;
    });

    // REMEMBER THAT SECONDS TAKES PRIORITY OVER RPM, SO IF RPM IS TO BE USED SECONDS MUST BE AT ZERO. WHAT THIS FUNCTION ACTUALLY DOES HERE IS CONVERT THE RPM TO SECONDS, WHICH IS WHAT THE SCRIPT ACTUALLY USES
    if (this.firerateS === 0) {
        Realrate = (1 / (this.firerateRPM / 60))
    } else {
        Realrate = this.firerateS
    }

    // THREE DEBUG FUNCTIONS BELOW CAN BE REMOVED
    FirerateinS = Realrate
    FirerateinRPM = Math.round(60 / Realrate)
    Firemode = "FULL AUTO"

    // CHECKS IF PLAYER IS AIMING AND ACCURACY IS ADJUSTED
    if (this.app.mouse.isPressed(pc.MOUSEBUTTON_RIGHT)) {
        this.entity.setLocalEulerAngles((Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2));
    } else {
        this.entity.setLocalEulerAngles((Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2));
    };

    this.timer += dt;

    // CHECKS TO MAKE SURE BULLETS IS MORE THAN ZERO, THAT LEFT CLICK IS CLICKED, AND IF THE TIMER IS GREATER THAN THE FIRERATE REQUIREMENT
    if (Bullets > 0) {
        if (this.app.mouse.isPressed(pc.MOUSEBUTTON_LEFT)) {
            if (this.timer > Realrate) {
                if(!this.shotgun) {
                    anglePos = this.entity.forward.clone();
                    anglePos.scale(this.range);
                    from = this.entity.getPosition();
		            result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                    this.entity.children.forEach((entity) => {
                        entity.enabled = true;
                    });
		            if(result){
			            if(result.entity.tags.has(this.enemyTag)) {
		                    result.entity.translateLocal(0,-50000,0);
				            result.entity.sound.play("sound");
				            Grams += 1;
			            };
                    };
                } else {
                    for(i=0;i<this.bulletCount;i++) {
                        if (this.app.mouse.isPressed(pc.MOUSEBUTTON_RIGHT)) {
                            this.entity.setLocalEulerAngles((Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2), (Math.random() * this.accuracy) - (this.accuracy / 2));
                        } else {
                            this.entity.setLocalEulerAngles((Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2), (Math.random() * this.inaccuracy) - (this.inaccuracy / 2));
                        };
                        anglePos = this.entity.forward.clone();
                        anglePos.scale(this.range);
                        from = this.entity.getPosition();
		                result = this.app.systems.rigidbody.raycastFirst(from,anglePos.add(from));
                        this.entity.children.forEach((entity) => {
                            entity.enabled = true;
                        });
		                if(result){
			                if(result.entity.tags.has(this.enemyTag)) {
		                        result.entity.translateLocal(0,-50000,0);
				                result.entity.sound.play("sound");
				                Grams += 1;
			                };
                        };
                    }
                }
                this.entity.sound.play("sound");
                this.timer = 0;
                Bullets -= 1;
                Missing += 1;
                Recoilburst = 1;
            };
        }
    }
};

For shotguns you can delete all the child entities, they do nothing but add lag. For regular guns you must remove the bullet scripts from the bullets as they will break the gun.
I am currently working on the grenade script.

What about the automatic shotgun? How do I enable that?

You just have to have the fullauto script and set it up to be a shotgun
Screenshot 2024-10-27 22.27.39